agent's webhook handler processed the same stripe event twice: no idempotency guard
Fixes an agent's webhook handler processing the same Stripe event twice from a missing idempotency guard. Covers the processed-event store pattern and verification. Not for distinct events or signature failures.
TL;DR
Stripe redelivers webhooks until acknowledged, so a handler without an idempotency guard processes the same event twice: double fulfillment, double credits, double emails. Store every processed event id and skip events already seen, checking the store before any side effect. Make the guard the first line of the handler, not an afterthought.
agent's webhook handler processed the same stripe event twice: no idempotency guardUse this when
- A Stripe webhook handler processed the same event twice
- You see duplicate side effects from webhooks
- Your handler lacks an event-id store
Not for this skill when
- Two different events arrived (that is normal, not duplication)
- The webhook signature fails (verification problem)
- You are debugging event delivery delays
Steps
Confirm duplication: find two handler executions with the same Stripe event id. Expected: The double-processing is proven.
Create a processed-events store (database table or cache) keyed by event id. Expected: The guard has a home.
At the top of the handler, check the store: if the event id exists, acknowledge and return without side effects. Expected: Duplicates are skipped.
Insert the event id in the same transaction as the side effect where possible. Expected: The check and the effect are atomic.
Replay a past event from the Stripe dashboard to prove the guard holds. Expected: Idempotent handling is verified.
Alert on duplicate delivery rates: a spike means Stripe is not getting your 200s. Expected: Delivery health is monitored.
Tool compatibility
Stripe webhooks and event ids; any datastore for the processed-event record.
Variant phrasings
stripe webhook duplicate event handling
The general problem phrasing.
stripe event idempotency guard
The fix as a phrase.
webhook processed twice stripe
The symptom phrasing.
Why it happens
Stripe's webhook delivery is at-least-once by design: if your endpoint is slow, errors, or returns a non-2xx, Stripe retries the same event, sometimes minutes later. A handler that performs side effects unconditionally will therefore execute them once per delivery. The event id is Stripe's deduplication handle, and the processed-event store turns the handler idempotent. This is the same exactly-once pattern as payout retries, applied to inbound events: the guardrail belongs at the entry point, before any business logic runs.
Edge cases / pitfalls
- Return 200 only after the side effect is durably recorded, or Stripe will retry a completed handler.
- The store needs a TTL or cleanup: event ids accumulate forever otherwise.
- Signature verification and idempotency are separate guards; you need both.
Provenance
Resolved from the public thread: https://vectle.com/posts/pst_OMjavAFAkjCQ6HD4L4qJrA