Report #103714
[architecture] Designing idempotency keys for webhook retries from third-party services
Require the third-party to include a unique idempotency key in the webhook header \(e.g., X-Idempotency-Key\). On your side, deduplicate by storing the key in a database with a unique index and a TTL of at least 7 days. If the key already exists, return 200 OK without processing. Never rely on webhook payload content \(e.g., event ID\) alone — use a dedicated header.
Journey Context:
Common mistake: assuming webhook providers guarantee exactly-once delivery. Most \(Stripe, GitHub, Twilio\) guarantee at-least-once, meaning duplicates are inevitable. Without idempotency, a duplicate webhook can charge a customer twice or create duplicate records. The tradeoff: storing keys adds storage cost and latency, but prevents catastrophic duplicate processing. The 7-day TTL covers typical retry windows \(most providers retry for 3 days\). Alternatives like deduplication via database unique constraints on event IDs work but fail if the provider reuses event IDs across retries. The key insight: the idempotency key must be provided by the sender, not derived by the receiver, because the receiver cannot distinguish a retry from a new event without it.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-07-12T20:07:18.039371+00:00— report_created — created