One webhook for every notification: how onboarding a client became a config change, not a workflow edit
Centralizing notification routing in one dispatcher moves client-specific rules into CRM records while enabling safer testing and rollback.
When a client goes live on a new system, the real work often isn't the new software. It's the notification sprawl that comes with it. Every workflow — onboarding, billing, order status, support tickets — sends its own emails and SMS messages. Each one has its own templates, its own triggers, its own logic for who gets told what and when.
Then a new client joins with slightly different requirements. They want SMS instead of email for payment reminders. They want the account manager copied on support notifications. They want a delay before the final notice goes out.
That used to mean opening the workflow editor and changing the logic. For each client. For each channel. For each timing rule.
The problem: notification logic scattered across every workflow
Consider a typical operations stack. A CRM holds an order. An invoicing system tracks payment. A support tool manages tickets. Each of these systems has workflows — rules like "when an invoice is due, send a reminder."
The first version of these workflows usually looks reasonable. The invoice workflow sends an email when payment is due. The order workflow sends an SMS when a shipment ships. The support workflow sends a notification when a ticket is created.
Then the requirements grow. A client wants their name on every message. Another wants a different sender ID. A third wants billing notifications suppressed for certain account types. Each new requirement means editing each workflow individually. One workflow sends email. Another sends SMS. A third sends both.
Now the notification logic exists in multiple places. To change how a client is notified, you edit multiple workflows and hope they stay in sync. You test across five different paths. You miss one, and a client's account manager doesn't get the escalation email they were promised.
The problem isn't the volume of notifications. The problem is that notification rules live inside each workflow, embedded in the logic of processes that have nothing to do with messaging.
What this costs operationally
- Configuration drift. The same client is configured slightly differently across each workflow. One sends email; another sends SMS. Reconciliation becomes a manual effort.
- Slow onboarding. New clients require workflow edits, testing, and deployment cycles. That delays go-live and ties up engineers or admins on simple configuration changes.
- Unclear audit trail. When a notification goes wrong, you have to trace through multiple workflows to find the culprit. Was it the template? The trigger? The channel mapping?
- High maintenance burden. Every change to notification behavior is a change to workflow logic, which means every change risks breaking something unrelated.
The root cause is a missing boundary. Notifications are a transport and routing concern, but they're being implemented as part of every workflow's business logic.
The shift: one webhook for every notification
The alternative is to separate the decision to send a notification from the mechanics of sending one.
Instead of each workflow knowing how to send email and SMS, every workflow does one thing: it POSTs a structured event to a single endpoint — a Notification Dispatcher webhook. That endpoint owns all routing rules.
The workflow says, in effect: "The order shipped" or "The invoice is overdue." It does not say who to notify, through which channel, with what template, or after what delay. That information lives elsewhere.
This is a meaningful architectural distinction:
Before
Before: The workflow knows the business event and the recipient and the channel and the timing. It is responsible for all of it.
After: The workflow knows only the business event. It sends a neutral, structured notification of that event to the dispatcher. The dispatcher decides everything else.
After
The webhook becomes the single place where notification behavior is defined. The workflow no longer needs to change when notification rules change.
How it works: routing rules in CRM records
The key insight is where the routing rules live. They don't live in code. They live in CRM records, keyed by four dimensions:
Routing dimensions
Outcome — what happened (order shipped, invoice due, ticket escalated).
Recipient — who should be notified (client, internal team, account manager).
Channel — how they should be notified (email, SMS, both).
Timing — when they should be notified (immediately, after 24 hours, only during business hours).
Example preferences
Acknowledgment of a new order → customer via email → immediately.
Payment overdue by 7 days → customer via SMS → at 9 AM their local time.
Recurring billing failure (3 attempts) → customer via email + account manager via email → immediately.
Support ticket escalated → account manager via SMS → immediately.
In practice, this means the CRM stores a notification preference record for each client. That record might say:
The dispatcher receives a webhook from any workflow — maybe a POST with a payload like:
{
"event": "invoice.overdue",
"client_id": "acme-001",
"data": {
"invoice_number": "INV-2024-001",
"days_overdue": 7
}
}
The dispatcher looks up the client's notification preferences in the CRM, determines the recipient, channel, and timing for that outcome, and sends the messages via the appropriate providers.
The workflow's only job is to emit an accurate description of the business event. It doesn't care whether the client prefers email or SMS. It doesn't care about timing windows. It doesn't care about templates. All of that is configuration.
Why this is more than a convenience
The value isn't just fewer edits. It's a structural change in how the system behaves.
Onboarding becomes configuration
When a new client joins, you create a notification preference record. You populate the outcomes, recipients, channels, and timing for that client. Done.
You do not touch a single workflow. You do not redeploy. You do not retest five paths. The workflows were already emitting the events; the dispatcher now routes them according to the new client's preferences.
Onboarding as config
This turns client onboarding from a workflow-engineering exercise into a data-entry exercise.
Audit in one place
To debug a missed notification, you inspect the dispatcher's log for that event. You see what the workflow sent, what the routing rules resolved to, and why the message didn't go out.
Deterministic routing
Octacer's preference for the smallest credible solution applies here. You do not need a probabilistic system to route a notification. You need a deterministic system that reliably consults a source of truth. The CRM record is that source of truth. The dispatcher is a faithful executor.
Notification behavior is auditable in one place
To understand how a client is being notified, you read one CRM record. You don't trace through multiple workflows trying to reconstruct the logic from context.
To change notification behavior, you update one record. The change applies uniformly to every workflow that emits the relevant event.
Deterministic routing where it belongs
Notice that the dispatcher is not an AI system making judgment calls. It's a deterministic routing engine. Given the same event and the same CRM record, it produces the same result every time. That predictability is exactly what you want for notifications.
The intelligence is in the preferences — the human decision about who should be told what, when, and through which channel. The dispatcher simply executes those preferences consistently.
Implementation considerations
A few details matter for this to work well in production.
The webhook payload must be event-shaped, not channel-shaped
The workflow should describe the business event, not a particular message. It should say "invoice.overdue" with relevant data, not "send an email to this address with this subject line."
Event-shaped payloads
This separation is what gives you flexibility. If a client later wants SMS instead of email, the workflow doesn't change. The routing rule changes.
Clear failure modes
The goal is that a configuration error is loud, not silent.
Versioned preferences
Keep the preference record append-only or versioned rather than overwriting in place.
Scheduled delivery
The dispatcher should persist the intent to send, record when it should execute, and deliver when the schedule says so.
The dispatcher needs a clear failure mode
When a notification can't be delivered, the dispatcher should log it and retry with backoff. When a client's preferences are missing or incomplete, the dispatcher should have a sensible default — and it should flag the gap rather than silently doing nothing.
Preference changes should be versioned
If a client updates their notification preferences, you want to know when that happened and what the previous state was. This matters for auditing and for understanding delivery history.
Timing rules need a scheduler
Some routing involves delay — "notify after 24 hours" — which means the dispatcher needs a way to schedule future sends. This is a queue with a scheduled delivery time, not a background task that fires immediately.
What good looks like
When this is working, several things become visible:
- New client onboarding is fast. You add a preference record and the system handles the rest. No workflow edits, no redeployments.
- Consistent behavior. A client's notification preferences are honored uniformly across every workflow that emits an event. No drift between paths.
- Debugging is localized. A missed notification is traced to one dispatcher event, not investigated across multiple workflows.
- Changes are reversible. Update the preference record, and behavior changes immediately. If it's wrong, change it back.
- The workflows are simpler. Each workflow has less logic. It emits an event and trusts the dispatcher to route it.
Where this could go wrong
This pattern is not a universal answer.
The pattern pays off when there are multiple workflows, multiple channels, and — critically — clients with differing notification preferences. That's the combination that makes scattered configuration painful.
There's also a temptation to make the dispatcher too clever. Resist it. The dispatcher should route and deliver, not interpret. If you need to understand the content of a message or make a judgment about whether a notification is appropriate — that's a candidate for a different kind of system, where a human or an AI evaluates context. Don't overload the dispatcher with decisions that don't belong there.
A practical next step
If this pattern sounds relevant to how your systems currently behave, the useful exercise is to map your current notification landscape.
Go through your workflows and list every place that sends an email or SMS. Ask each one:
- What business event triggers this notification?
- Do I know the recipient, channel, and timing — or does this workflow hardcode them?
- Would a new client with different preferences require a workflow edit?
If the answer to that last question is "yes" more than once, you have notification logic scattered across your workflows. Worth mapping the workflow?
That map — every notification trigger, every hardcoded recipient, every channel decision embedded in workflow logic — is the starting point. Once you see the full surface area, you can decide whether consolidating behind a single dispatcher is the right move. In most cases where a system already supports multiple clients and multiple channels, the consolidation pays for itself the first time a new client goes live without a single workflow edit.
Ready to Implement These Strategies?
Let's discuss how to apply these insights to your specific business challenges.
Schedule Consultation