Quick Summary — TL;DR
A webhook retry is the automatic re-sending of a webhook payload after the initial delivery attempt fails. If the receiver returns an error status code (5xx), times out, or the connection is refused, the sender waits and tries again — typically with increasing delays between attempts.
Webhooks are fire-and-forget HTTP requests. Unlike API calls where your code waits for a response, webhooks are sent by an external system to yours. If delivery fails and there's no retry mechanism, that event is gone. Your system never learns about the payment, the deployment, or the status change.
Real-world failures happen constantly: network timeouts, brief deployments, load balancer hiccups, rate limits. Retries turn webhook delivery from "best effort" into something you can actually rely on.
The most widely used approach is exponential backoff — doubling the delay between each attempt. A typical schedule looks like:
| Attempt | Delay after failure | Total elapsed |
|---|---|---|
| 1 | Immediate | 0s |
| 2 | 30 seconds | 30s |
| 3 | 2 minutes | ~2.5 min |
| 4 | 10 minutes | ~12.5 min |
| 5 | 1 hour | ~1 hour |
Adding jitter to these intervals prevents synchronized retry storms when multiple webhooks fail at the same time.
Not every failure deserves a retry. The response status code tells you whether retrying makes sense:
Retry-After header if present.When all retry attempts fail, the webhook needs to go somewhere. Most systems move exhausted deliveries to a dead letter queue where they can be inspected and manually replayed. Without a DLQ, failed events disappear silently.
Recuro automatically retries failed webhook deliveries with configurable backoff and moves exhausted attempts to a dead letter queue for manual review, so you never lose critical events.
If you're building the receiver, your endpoint must be idempotent. Retries mean the same event may arrive more than once — your handler needs to produce the same result regardless of how many times it processes the same payload. Use the webhook's event ID or delivery ID to deduplicate.
Most webhook providers retry 3 to 5 times over a period of hours. For critical events (payments, account changes), some providers retry up to 10 times over 24 hours. The right number depends on how critical the event is and how long the receiver might be down.
After all retries are exhausted, the delivery is marked as failed. Good webhook senders move it to a dead letter queue and may disable the endpoint after repeated failures to avoid wasting resources. The subscriber should monitor delivery health and fix the endpoint.
No. A 400 means the receiver understood the request but rejected it — usually due to a validation error or malformed payload. Retrying the exact same payload will produce the same result. Fix the payload or endpoint logic instead.
Webhook retries are a core part of any retry policy and rely heavily on exponential backoff to avoid overwhelming receivers. When retries repeatedly hit webhook timeouts, it's a signal the endpoint may need a circuit breaker. Failed deliveries that exhaust retries belong in a dead letter queue. Because retries inherently mean multiple deliveries, they provide at-least-once delivery semantics, making idempotency essential on the receiver side. You can test your webhook endpoint's retry behavior with the webhook tester.
Recuro handles cron scheduling, retries, alerts, and execution logs -- so you can focus on building your product.
No credit card required