What makes a webhook service reliable?
A reliable webhook service delivers every event to every subscribed endpoint at least once and can prove it. It stores the event before the first attempt, retries failures on a published exponential backoff schedule for a day or more, signs each attempt, isolates endpoints that keep failing, and keeps exhausted deliveries in a searchable log you can replay from.
Reliability is a set of numbers, not an adjective
Every webhook service calls itself reliable. The word only means something attached to numbers you can check, and five of them decide whether events survive real failures: a customer deploying a bad build, an endpoint that hangs, a receiver down for a weekend.
| Property | What to look for | What it protects against |
|---|---|---|
| Durable storage before sending | The event is written to storage in the same transaction as the change that caused it, then delivered by a separate worker | An application that commits, crashes, and never sends |
| Published retry schedule | Exponential backoff with jitter over a day or more, the exact intervals documented, and only a 2xx counting as success | A receiver that is down for a deploy or an outage |
| Timeout and isolation per endpoint | A per-attempt timeout measured in seconds, a concurrency cap per endpoint, and automatic disabling after days of failure | One slow customer occupying the workers that serve everyone else |
| Signature on every attempt | HMAC-SHA256 over a timestamp and the body, regenerated for each retry so the timestamp stays inside tolerance | Forged, tampered, and replayed requests, and retries that fail verification |
| Replayable delivery log | Every attempt stored with its response, a message ID that stays the same across retries, and replay per message or in bulk by time range | Events lost after the schedule runs out, and support tickets nobody can answer |
If a vendor cannot state all five in numbers, treat the reliability claim as unverified. The webhook reliability guide explains the mechanism behind each row. This page is about recognizing those mechanisms in a service you are evaluating.
Reliable webhook service examples
The numbers mean more side by side. These are the published behaviors from our webhook reviews, next to the default schedule of a service built for sending.
| Service | Retry schedule | What happens after the schedule |
|---|---|---|
| Stripe | Up to three days with exponential backoff in live mode | Events can be resent by hand from the Dashboard for up to 15 days |
| Shopify | 19 attempts over 48 hours | The endpoint is disabled |
| GitHub | No automatic retries | Manual redelivery from the Recent Deliveries tab, which keeps three days of history |
| PagerDuty | 4 attempts over 20 minutes | Delivery stops |
| Svix | 8 attempts over a little more than 27 hours: immediately, then after 5 seconds, 5 minutes, 30 minutes, 2 hours, 5 hours, 10 hours, and 10 hours | The endpoint is disabled after five days of failure, and failed messages can be replayed one at a time or in bulk from a chosen date |
The spread is the point. PagerDuty’s 20-minute window means an endpoint that is down over lunch loses events, GitHub’s missing retries move the whole recovery job onto the receiver, and Stripe’s three-day window covers a long weekend. The retry window tells you how long a customer’s endpoint can be down before data disappears, so ask for it first. Timeouts vary the same way: Shopify counts a delivery as failed after 5 seconds and GitHub after 10, which webhook timeout best practices covers from the receiver’s side.
How to check a service before you trust it
A demo shows a healthy endpoint receiving events, which proves nothing. During the trial, register one endpoint that always returns 500 and one that sleeps for 30 seconds, send a burst, and read the attempt log. The gaps between attempts are the real retry schedule, the message ID should be identical on every attempt, and a healthy endpoint registered at the same time should keep delivering at full speed. Our guide to evaluating webhook infrastructure has the test receiver to run and the security and procurement questions that follow.
Reliability also depends on the receiver
Even a perfect sender delivers at least once, not exactly once: a delivery that times out after the receiver processed it is retried, and a retried event can land after a newer one. A reliable service gives receivers what they need to cope: a stable message ID to deduplicate on, a timestamp or sequence number to discard stale updates, and a short timeout that rewards returning 2xx before doing the work. Idempotency and deduplication covers the receiving half, and what happens when a webhook fails shows how each failure looks in a delivery log.
Build one or use one
A first version is a queue and a worker pool, shipped in a few weeks. The reliable version is the five rows above running together: retry state that survives a crash, per-endpoint isolation, attempt history, a dead letter queue with replay, and someone on call for it. That is the webhook infrastructure most teams end up rebuilding, and why webhooks as a service weighs the cost of owning it.
Svix runs that layer as a service. Messages follow the eight-attempt schedule in the table above with a 30-second timeout per attempt, an endpoint that fails every attempt for five days is disabled with a notification to its owner, and failed messages can be recovered individually or in bulk through the API or the App Portal your customers use. The exact rules are in the Svix retry docs.
Frequently asked questions
How many retries does a reliable webhook service make?
Around eight attempts with exponential backoff spread over a day is a common design, and Stripe retries for up to three days. The count matters less than the total window and whether it is published, because the window is how long a receiver can be down without losing events.
Can a webhook service guarantee exactly-once delivery?
No. A delivery that times out after the receiver processed it has to be retried, so every real system is at-least-once. A reliable service makes the duplicates harmless by sending a message ID that stays the same across retries and replays, so the receiver can deduplicate on it.
Why do webhooks from a reliable service still fail?
Usually because of the receiver: it is mid-deploy, it does slow work before answering and trips the timeout, or it returns 400 for a payload it will never accept. The service retries the transient cases, parks the permanent ones with their response bodies, and tells the endpoint owner.