The engineering bottleneck with assembled stacks
Outbound webhooks fail in the worst direction: your customer’s endpoint was down for an hour, the events they paid to receive are gone, and your record of the loss is a log line. Support asks engineering to “resend Tuesday’s events”, engineering writes the script everyone is afraid of, and the customer learns your delivery guarantees are vibes.
Architecture on the Software Lifecycle Cloud
Emitters write delivery rows instead of calling out directly — same transaction of intent as the domain event itself. The delivery worker claims rows whose next-run time has arrived, posts with a timeout, and writes the outcome back: delivered with the response code, or rescheduled with exponential backoff and the error verbatim. After the attempt budget, the row parks in a failed state that a human step can release after the customer confirms their endpoint lives.
The customer-visible delivery log
Because attempts are rows, the delivery history a customer asks for already exists: every attempt, timestamp, response, and error. Surfacing it — even as a support-side query — ends the screenshot negotiation. Internally, the same rows power the only retry metric that matters: how many deliveries are in the failed state right now, per destination.
- Replay is a state change on a row, performed from data, with the new attempts appended to the same history
- Backoff and attempt budgets are worker code — tunable per destination without a platform ticket
- Endpoints that stay down stop consuming retries when the budget ends; the record stays
Signing and honesty at the edges
Deliveries are signed with project secrets so receivers can verify origin, and responses are stored verbatim — including the embarrassing ones — because “their endpoint returned 500 with this body” settles more arguments than any dashboard. What the pattern cannot do is make the other side’s endpoint reliable; it makes unreliability visible, bounded, and recoverable.
Frequently asked questions
By next-run timestamps on the delivery rows, walked by a worker. Backoff policy — interval growth, attempt budget, jitter — is ordinary worker code, so a chronically failing destination can be given a longer leash without touching healthy ones.
Yes. Releasing a failed row resets its next-run time; the worker delivers it and appends the attempt to the same history. No script, no laptop, no production shell — the operation is a reviewed state change.
If you surface it — the rows support it directly. Many teams start with support-side visibility and later expose the same per-customer view in their portal; the data never had to move.
Related capabilities, architectures, and comparisons
Ship your stack on the Software Lifecycle Cloud.
Closed preview on dedicated European infrastructure. Bring a repository or start from a blueprint.