What it actually takes to ship outbound webhooks
An enterprise prospect asks whether you support webhooks. The answer decides the deal, so someone estimates the work: fire a POST when something happens. A week, maybe less.
That estimate is usually wrong, and it goes wrong in a predictable way. Sending the request is the easy part. The work is in everything around it, and most of that only shows up once the first version is running in production.
Here is the list, roughly in the order teams discover it. Use it to scope the build before you decide whether to build it at all.

1. Delivery state, per endpoint
The first version stores an event and fires a request. The second version has to answer a question the first cannot: what happened to this delivery, for this endpoint?
You need a record per attempt (not per event), because one event fans out to many endpoints and each of them succeeds or fails separately. That record needs the endpoint, the attempt number, the response status, the response time and the error if there was one.
Teams that skip this end up debugging customer reports by grepping application logs. That works until the logs roll over, which is usually about the time the first serious customer asks.
2. Retries with exponential backoff
A failed delivery has to be retried, and the retries have to back off. Fixed-interval retries against an endpoint that is down turn your integration into a small denial of service attack on your own customer.
Decide these up front, because they are hard to change later:
- How many attempts before you give up (5 to 8 is typical)
- The backoff curve, and whether you add jitter (you should, or all your retries land simultaneously)
- The total window before an event is considered permanently failed
- Whether a 4xx response should retry at all (usually not, except 408 and 429)
3. HMAC signing
Your customers need to verify that a request actually came from you. The standard approach is an HMAC signature over the payload, sent in a header, using a secret shared with that endpoint.
Two details matter more than the algorithm choice. Include a timestamp in the signed content, or you have handed anyone who captures one request the ability to replay it forever. And sign the raw request body, not a re-serialised version of it, because your customer will verify against the exact bytes they received.
You also have to write the verification snippet your customers paste into their own code. Their developers will search for it, so it is worth publishing properly.
4. Secret rotation
Customers will ask to rotate a signing secret. Sometimes because of policy, sometimes because someone pasted it into a support ticket.
Rotation is not a single write. There has to be a window where both the old and the new secret produce valid signatures, or every rotation causes a brief outage for that customer. That means the endpoint record holds a set of secrets rather than one, each with its own validity period.
5. Circuit breaking for dead endpoints
Some endpoints are not coming back at all, because the customer decommissioned the service and did not tell you.
Without circuit breaking, you retry those forever. Every event, every attempt, against a host that will never answer. It is invisible until you look at what your workers are actually spending their time on.
So you need consecutive-failure counting per endpoint, automatic disabling past a threshold, a way to notify the customer that it happened, and a way for them to re-enable it once fixed.
6. Fan-out
One event, many subscribers. This is the point where doing the work inline in your request handler stops being viable, because your API response time becomes a function of how many endpoints a customer has registered and how slow the slowest one is.
Delivery has to move to a queue. Your handler writes the event and enqueues one job per endpoint, then returns. Everything after that is a worker's problem.
7. Ordering (if you promise it)
Ordering is the item most likely to be assumed rather than scoped. If a customer processes subscription.updated before subscription.created, their state is wrong, and it is wrong in a way they will blame on you.
Strict ordering per endpoint means serialising delivery for that endpoint, which limits throughput and interacts badly with retries (a failing event blocks everything behind it). The usual compromise is to send a sequence number and let customers reorder if they care. Decide deliberately, and document whichever you chose.
8. The customer-facing delivery log
The first seven items are infrastructure that your customers never see directly. This one is part of your product, which is why it tends to fall outside the original estimate.
Your customers will want to see their own delivery history: which events were sent, which failed, what the response was, and a button to retry one. Without it, every failed delivery turns into a support ticket, and support load is the cost you actually feel month to month.
That means endpoint management (register, edit, disable, rotate the secret), a searchable delivery history scoped to that customer, response detail per attempt, and self-service replay.
This is a real UI, in your product, with authentication and tenant isolation. It is usually the largest single item on the list, and it is almost never in the original estimate.
How long does this take?
Items 1 through 7 are perhaps two to three weeks of work if you've done it before and nothing surprises you. Item 8 is usually where the rest of the quarter goes, because it's a real UI in your product rather than a background job.
That's why so many teams reach for a vendor at this point, and it's a reasonable thing to do.
Should you build or buy?
It depends mostly on one question: does it matter to you that your customers' payloads pass through someone else's infrastructure, and that your customers look at someone else's portal when a delivery fails?
Buy if webhook delivery isn't close to your product, nobody is asking where the data goes, and a vendor's portal on a vendor's domain is an acceptable part of your customer experience. Svix and Hookdeck's Outpost are good at this, they're well funded, and they've solved every item on the list above. Outpost is worth naming specifically, because Hookdeck's main product is an inbound event gateway and outbound sending is the separate service.
Build if your customers ask about data residency and subprocessors, if you want the delivery log inside your own product, or if you'd rather not have a third party sitting between you and the people paying you.
The build case has become easier recently, and item 8 is the reason. A portal on top of a schema that already exists is well-trodden work (the data model is defined and the CRUD is ordinary), so a coding agent handles a lot of it. The part that used to make ownership expensive has become a lot cheaper to build.
If you work this way, our AI agent setup guide covers the plugin, the MCP server and the coho prompt command that gives an agent the full API reference before it writes anything.
If you want to see it as running code, we ship a template for outbound webhook delivery with the endpoint records, signing, retries and delivery log already built. You build the UI on top.
Summary and conclusion
Sending an HTTP request when something happens is an afternoon of work. Shipping outbound webhooks as a product feature means delivery state per endpoint, backoff, signing, secret rotation, circuit breaking, fan-out, a decision about ordering, and a delivery log your customers can use without contacting support.
Scope item 8 before you commit to an estimate, whichever way you decide to go.
