Idempotency in practice: stopping duplicate orders and invoices
Webhooks are delivered at least once, not exactly once. A short guide to keys, dedupe windows and replay safety.
At-least-once delivery is the contract
Every major platform documents its webhooks as at-least-once. A network blip on the acknowledgement, a retry after a slow response, a manual replay during debugging — all of them deliver the same event twice. If your handler is not idempotent, each of those becomes a duplicate invoice.
Choose a stable idempotency key
The key has to come from the source event, not be generated on receipt. A Shopify order id, a payment reference, a composite of order-id plus event-type. Store it, and make the write conditional on it not already being present.
Dedupe windows and replay
Keep processed keys long enough to cover the platform’s maximum retry window plus your own replay habits — 30 days is a common choice. With that in place, replaying a day of events to recover from an outage is safe rather than terrifying.
Planning an integration?
Send us the two systems and the record types involved. We will come back with an outline scope and the approach we would recommend, within one working day.