How to replay a failed webhook safely
Replay re-runs a real event. Before you re-send it, check the original request, the target’s response, the attempt history, and how your handler treats duplicates.
Replay re-sends a webhook your provider already delivered once. It is the right way to recover a dropped event — but it re-runs the event’s side effects, so the same action that fixes one failure can create a duplicate charge or a duplicate order if you do it without checking. This guide is how to replay without causing new problems.
When replay is safe
- Your handler is idempotent — processing the same event id twice is a no-op the second time.
- The original delivery failed before doing any work (e.g. a
500thrown at the very start), so nothing partially happened. - The event is still current — you are not replaying a stale state change over a newer one.
When replay is risky
- Your handler is not idempotent and the event has money or messaging side effects (charges, refunds, emails, shipments).
- The delivery partially succeeded — some steps ran before it failed, so a replay repeats them.
- A newer event has already superseded this one; replaying rolls state backwards.
Idempotency keys and duplicate processing
The durable fix is to make replay boring: record a stable identifier — the provider’s event id,
delivery id, or an Idempotency-Key — the first time you process an event, and check
it before acting. If you have seen the id, skip the work and return 200. With that in place, a replayed invoice.paid that already processed simply acknowledges and does nothing,
instead of billing twice.
Side effects to watch
- Money — charges, refunds, credits, payouts.
- Records — a second order, ticket, or user row.
- Messaging — a duplicate email, SMS, or Slack post.
- Fan-out — your handler emits its own webhooks, so one replay can trigger many downstream events.
How to verify the result
Replay one delivery first, then check that the downstream state moved exactly once — one charge, one row, one email — before replaying the rest. If you cannot yet guarantee idempotency, treat replay as a manual, one-at-a-time operation and verify each one by hand.
The safe-replay checklist
- Confirm the root cause is fixed and deployed — debug it first.
- Open the failed delivery; read its request and response.
- Check the attempt history so you do not re-process an event that already succeeded.
- Confirm the handler is idempotent for this event, or plan to verify by hand.
- Replay a single delivery, then verify the downstream state changed exactly once.
- Only then replay the remaining deliveries.
This is the workflow HookWatch replay is built around: it shows you the request, response, and attempts for each delivery so you can make the call before you click, not after. Applied to payments, see Stripe webhooks.
Keep reading
Start debugging your webhooks.
Point one endpoint at HookWatch, capture a failure, and replay it once it’s fixed. Free during beta.