Designing Reliable Webhooks: Retry Policies and Idempotency

Best practices for building reliable webhook systems, including retry logic and security verification.

Published: January 25, 2026  |  Author: UniversalCodeStudio

The Internet is Unreliable

Webhooks are a way for your system to say 'Hey, this happened!' to another system. But what if the other system is down? Or returns a 500? Or takes 30 seconds to respond?

Exponential Backoff

If a delivery fails, do not retry immediately. Wait 1s, then 2s, then 4s, then 8s. This 'Exponential Backoff' prevents you from hammering a struggling server (which would only make their downtime worse). Use a queue system like RabbitMQ Dead Letter Exchanges to handle this automatically.

Security: Verifying the Sender

How does the receiver know the webhook came from YOU and not a hacker? Sign the payload with an HMAC-SHA256 signature using a shared secret. Send this signature in a header (e.g., `X-Signature`). The receiver computes the hash of the body and compares it.


                    // Verifying signature
                    $hash = hash_hmac('sha256', $request->getContent(), $secret);
                    if (!hash_equals($hash, $request->header('X-Signature'))) {
                        abort(403);
                    }
                    

Idempotency is Key

What if your webhook was processed, but the 'OK' response timed out? Your server might retry sending the same event. If that event was 'Charge $50', you just charged the user twice. The receiver MUST check the `Event-ID` against a database of processed events to prevent duplicates.

Related Articles