Skip to content

Knowledgebase

Handling webhook retries without duplicate actions

development

A provider may deliver the same event again after an uncertain response or an intentional redelivery. Design processing so a repeated delivery does not create a second external action.

What you need before you begin

Identify the provider’s stable event or delivery identifiers and the business operation being performed. Decide how completed, failed and in-progress work will be recorded.

01 Handle webhook retries without duplicate actions

  1. Authenticate the event before trusting its identifier. Store a provider-scoped identifier with an appropriate unique constraint or atomic duplicate-detection mechanism.

  2. Separate receipt from successful processing. An event being present in a table does not necessarily mean its business action completed.

  3. Claim the work atomically so concurrent deliveries do not both execute it. Record progress and the final result with enough information for recovery.

  4. Use an idempotency key or reconciliation check when the downstream API supports it. A timeout after sending a request can leave the remote outcome uncertain.

  5. On redelivery, return the appropriate acknowledgement for completed work or safely resume eligible unfinished work. Keep a deliberate retry and retention policy.

02 Example: prove that a repeated event creates one result

Use a harmless staging event that creates an internal test notification. The identifiers below describe a test fixture; adapt the field names to your provider rather than posting this invented schema to its API. Preserve the same stable event ID for the retry.

Structured data example
{
  "provider": "example-provider",
  "event_id": "evt_example_001",
  "event_type": "test.notification",
  "delivery_attempt": 2
}

Send the original event, wait for its durable state to become completed, then deliver the same event again. Next test two simultaneous deliveries. The provider and event ID should identify one durable job, with an atomic claim preventing both workers from performing it. A received row alone is not a completed result.

Expected result: There is one test notification and one completed business operation. Both deliveries receive the acknowledgement required by the provider. Repeat after a worker restart to establish that protection survives beyond process memory.

Confirm the expected result

Deliver the same harmless event twice and concurrently in staging. Confirm it produces one intended business result while both deliveries receive sensible responses.

Troubleshoot unexpected results

If duplicates already exist, reconcile the actual provider and application state before deleting records or replaying every event. A duplicate email and a duplicate financial operation require different recovery handling.

A common question

Can I simply remember event IDs in process memory?

That memory can disappear on restart and is not automatically shared across workers. Use durable, coordinated state for operations that must remain protected across deployments.

Was this answer helpful?

Need a little more help?

Our support team can help you find the next step.

Contact support

Powered by WHMCompleteSolution