From reading to action
A practical path through this guide.
Select a step to explore what to do and why it matters.
Choose the operation identity
Separate the source event from the specific business action.
An idempotent workflow produces the intended business effect once even when the same request arrives repeatedly. Duplicate delivery is normal enough that it should be a design input. The difficult part is coordinating the deduplication record with the actual external action.
Choose the right identity
Use a stable source event ID for delivery deduplication and a business key for the operation you intend to perform. A customer ID alone is too broad if the customer can place many orders. An order ID plus action type may be appropriate for one shipment notification.
Define how long the key must remain valid. A five-minute cache can suppress a rapid duplicate while failing to protect against tomorrow's manual replay. Retention should match the provider's delivery window and your own recovery practices.
Claim work atomically
A fragile implementation reads “has this key been processed?” and then writes it later. Two concurrent workers can both read “no” and perform the action. Use storage with a unique constraint or another atomic claim mechanism.
Track processing, completed, and unresolved states. If a worker crashes after claiming the key, a permanent lock would lose the record. Add a recovery procedure that distinguishes an abandoned claim from an external action that succeeded but was never acknowledged.
Handle the uncertain outcome
Consider a CRM create request that times out. The CRM may have saved the contact. Before sending another create request, look up the source identifier or use the provider's supported idempotency feature where available. Your local flag alone cannot make an arbitrary remote write exactly once.
For messages, record the destination message reference if the provider returns one. If the provider offers no deduplication or searchable correlation, document the remaining duplication risk and choose a conservative manual recovery policy for important actions.
Verify under concurrency
- Deliver one event three times sequentially.
- Deliver two copies at the same time.
- Crash after the external write but before local completion.
- Retry after the normal deduplication cache would expire.
- Reuse a customer ID for a genuinely new business operation.
The expected outcome is one intended effect per business operation, with unresolved cases visible. Check actual destination records after every case. Avoid declaring success solely because the second execution returned a green status.
Further reading
Stripe's webhook documentation discusses duplicate event delivery. Combine deduplication with the incident response runbook so manual recovery respects the same safeguards.
A few practical answers
Frequently asked questions
Is a customer ID enough to prevent duplicate workflow actions?
Not always. A customer may place several legitimate orders or enquiries. Separate delivery identity from the business operation so deduplication does not suppress valid work.
Why does checking a deduplication flag before writing still allow duplicates?
Two workers can read the same unclaimed state concurrently. Claim the operation atomically with a unique constraint or equivalent mechanism before performing the action.


