An operation is idempotent if performing it multiple times produces the same result as performing it once. DELETE /users/42 is idempotent — deleting twice doesn't change the outcome. POST /charges is not — each POST creates a new charge.
Idempotency matters in webhook systems because duplicates always arrive. The provider retries on slow responses; the relay retries on failures; replays re-fire successful deliveries. Without idempotency, every duplicate produces an unwanted side effect: a double charge, a duplicate user, a doubled email.
How to make non-idempotent operations safe
The standard pattern is an idempotency key — a unique value attached to each request. The receiver records the key and refuses to re-process the same one twice.
In HTTP, the convention is the Idempotency-Key header. The sender generates the key; the receiver stores it with the response; future requests with the same key return the previous response without re-running.
For webhooks specifically:
- Inbound (your handler): dedupe on the provider's event ID (
event.idfor Stripe,X-GitHub-Deliveryfor GitHub,svix-idfor Standard Webhooks). - Outbound (your sender): include an idempotency key so your customer's handler can dedupe.
Hooksbase honors the Idempotency-Key header on every ingest call, and forwards a unique webhook-id header on every dispatch (Standard Webhooks-compatible).
For the deeper guide: The complete guide to idempotency keys.
Related terms
- Webhook
An HTTP request one service sends to another to notify it that something happened.
Read - Retry
Re-attempting a failed delivery on a backoff schedule until it succeeds or hits a retry budget.
Read - Replay
Re-running a retained event with the same input — typically after fixing a bug that caused the original to fail.
Read - DLQ (Dead-Letter Queue)
A holding area for messages that failed terminally so they can be inspected and recovered.
Read