
Webhooks: Turning duplicate deliveries into a single action
One new enquiry should create one CRM record. Then a response takes too long, the sender retries, and two records appear in the board. These failures occur at system boundaries. A dependable workflow needs to account for retries during design rather than cleaning up duplicates afterwards.
Research checked: 2026-09-09 · Cover: AI-generated illustration
A repeated delivery is not a new instruction
Stripe documents that webhooks can arrive more than once and that a particular event order must not be assumed. Its guidance recommends recognizing processed event IDs. This is a concrete instance of a broader integration problem.
For a custom interface, I would distinguish a transport event from the business operation it describes. Different notifications can concern the same operation. Comparing only timestamps or message text provides a weak foundation.
Persist acceptance of the work
My design starts with verifying the sender, enforcing an appropriate payload limit and storing an event ID. Acknowledgement follows reliable recording of the work. A worker can then carry out slower downstream operations.
A unique database key prevents two simultaneous copies from both being treated as new. A separate “check first, write later” sequence without shared protection can still duplicate work when requests run concurrently.
Protect the next boundary too
When a worker calls another API, a second failure boundary appears. Stripe provides idempotency keys for certain API requests so a retry does not accidentally create another operation. That does not replace deduplication of incoming webhooks.
I would use a stable key for each business action and preserve it across retries. If the destination provides no equivalent protection, an ambiguous timeout requires checking the actual destination state before trying again. Blind resending is not a dependable strategy in that situation.
The workflow at a glance
- 01AcceptPersist the event
- 02ProcessRecognize duplicates
- 03ReconcileConfirm destination state
Failures I would trigger deliberately
Acceptance tests for a CRM integration should include simultaneous duplicate deliveries, worker restarts and a timeout after the destination has already succeeded. Each attempt needs an understandable final state: processed, pending or requiring investigation.
The dashboard should expose outstanding work and provide controlled retries. This is particularly useful for outreach tools: a duplicate internal record may be repairable, but a duplicate message has already reached its recipient.
