Backoff instead of loops
Retry temporary failures with increasing delays so a recovering endpoint is not flooded.
Webhook retry guide
Retrying a webhook is easy. Retrying safely means classifying failures, slowing down with backoff, preserving delivery logs, and assuming the receiver may see the same event twice.
// Receiver-side idempotency shape
const inserted = await db.processedWebhook.createMany({
data: { idempotencyKey: event.idempotencyKey },
skipDuplicates: true
});
if (inserted.count === 0) {
return Response.json({ ok: true, duplicate: true });
}Retry temporary failures with increasing delays so a recovering endpoint is not flooded.
Use stable event keys so duplicate deliveries do not create duplicate business side effects.
Store every status code, response body, latency, and final failure state for debugging.
Not every webhook failure deserves the same retry behavior. Timeouts, connection errors, 429 responses, and 5xx responses are often temporary. Most 4xx responses usually need customer action, not an infinite retry loop.
A useful retry system separates temporary failures from permanent failures. It should retry when recovery is plausible and stop when the request is invalid, unauthorized, or unsafe.
Backoff increases the delay between attempts. The goal is not just to improve success rate. It is to avoid turning one customer outage into a burst of repeated HTTP calls.
A common shape is immediate delivery, then retry after a short delay, then progressively longer delays until the job succeeds or reaches its final failure state.
A sender can time out even if the receiver processed the request. From the sender side, retrying is correct. From the receiver side, processing the same event twice may be dangerous.
That is why important webhooks need stable event IDs or idempotency keys. The receiver should claim the key atomically before running irreversible work.
A retry policy without logs is hard to support. Teams need to see when each attempt happened, what status code came back, how long the request took, and whether another retry is scheduled.
Webhook Scheduler records delivery attempts so developers can inspect the timeline from the dashboard instead of searching through application logs.
Build retry logic yourself if webhook delivery is core infrastructure for your product. Use a managed scheduler when the requirement is reliable delayed HTTPS delivery with logs and retries.
For product-specific examples, see automatic webhook retries and billing retry workflows.
Timeouts, connection errors, 429 responses, and 5xx responses are usually retryable. Most 4xx responses are usually terminal.
Retries can deliver the same event more than once if the receiver processed the request but failed to return a response in time.
Yes. Delivery attempts include status, latency, errors, and response details so failed jobs can be inspected.
Start with the free plan, test a real delivery, then upgrade when the workflow becomes production critical.
Create a free account