Imagine an automation that creates a follow-up task when a customer issue arrives. One day it creates two tasks. The next day it creates none. The diagram still looks right. What is missing is a plan for messages that arrive twice, arrive late or disappear before the work is finished.

IN BRIEF

Treat “message received” and “job completed” as separate events. Save a verified message before acknowledging it, protect the resulting action against duplicates, and keep a recovery path for missed deliveries. The exact design depends on the sender’s retry rules and what the destination can safely repeat.1, 3, 4

Five failure cases to rehearse. Send the same event twice, including concurrent deliveries. Confirm the business action…: 01. Stop the worker after receipt. Confirm pending work survives the restart.: 02. Stop after the destination action but before recording completion. Confirm recovery does…: 03. 3 of 5 entries shown. Selected labels are abbreviated. Full detail appears in the article.
Five failure cases to rehearse. 3 of 5 entries shown. Selected labels are abbreviated. Full detail appears in the article.

A webhook is one application notifying another that something happened. The difficult part is not receiving a message. It is knowing whether the business action that follows it actually happened, and recovering without doing it twice.

Two documented delivery rules worth knowing1, 2, 3
Delivery behaviorGitHubStripe
A delivery failsNo automatic redelivery. Recovery can be manual or implemented in code.Live-mode delivery attempts can continue for up to three days.
A message is delivered againA requested redelivery keeps its X-GitHub-Delivery identifier.The same event can arrive again. Track processed event IDs.

These are different delivery contracts, not a reliability ranking. An integration that waits for the sender to try again needs another recovery path when the sender is GitHub. A retrying sender still needs a receiver that can handle repeats.

Save the message before saying “got it”

First verify the sender and event. GitHub recommends a webhook secret, HTTPS and a successful response within ten seconds. It suggests using a queue for background processing. Stripe also recommends signature verification and asynchronous processing.2, 3

Our proposed design is to save the accepted event in storage that survives a restart, then acknowledge it. A worker handles the slower job afterward. Record the event ID, account or installation, relevant object and processing status. Store only the payload fields you need, with appropriate access controls.

Return to the example: the message is saved, the receiver replies, and the worker crashes. The saved event is still pending. Another worker can find it. Reply before saving, however, and a crash can leave nothing to recover.

Do not confuse a repeat message with a finished task

An event ID answers “have I received this notification?” An operation ID answers “have I already performed this particular action?” Those are different questions. Seeing an event before does not mean its task was completed.

Amazon’s idempotent API guidance describes a caller-supplied identifier that lets a service recognize retries of the same intended operation. It also explains why saving that identifier and making the associated change must happen together, rather than leaving one recorded without the other.4

For the follow-up example, identify the operation using the account, issue and “initial follow-up” action. A reopened issue might legitimately need another task. Define that rule before treating everything about the same issue as a duplicate.

Protect concurrent workers with a uniqueness constraint or an equivalent all-or-nothing operation. When the destination supports an idempotency key, reuse it for the same action and check how long that protection lasts. A queue alone does not guarantee that an action in another service happens exactly once.

The dangerous gap comes after the action succeeds

Suppose the destination creates the task, but your worker crashes before recording success. Blindly sending “create task” again may make a duplicate. Recover the original result through the destination’s supported idempotency or lookup mechanism. When neither can establish what happened, ask an operator to reconcile it.

Also plan for events arriving in the wrong order. Stripe explicitly does not guarantee event order. A current-status dashboard may be repaired by fetching the object’s latest state. That does not reconstruct every historical action that should have happened during an outage.3

Five failure cases to rehearse

  1. Send the same event twice, including concurrent deliveries. Confirm the business action follows your duplication rule.
  2. Stop the worker after receipt. Confirm pending work survives the restart.
  3. Stop after the destination action but before recording completion. Confirm recovery does not blindly create another result.
  4. Send an old event after a newer one. Check the intended ordering or current-state rule.
  5. Take the endpoint offline, then recover missed deliveries through the sender’s actual supported options.

Give pending and uncertain work an owner. A green response means the message crossed one boundary, not that the customer’s job is finished. The practical test is whether your team can explain and repair the gap without comparing every record by hand.

Sources and methodology

Sources checked September 21, 2026. Dates and periods for individual figures are stated beside them.

  1. GitHub: handling failed webhook deliveriesAccessed 2026-09-21
  2. GitHub: best practices for webhooksAccessed 2026-09-21
  3. Stripe: receiving events in a webhook endpointAccessed 2026-09-21
  4. Amazon Builders’ Library: making retries safe with idempotent APIsAccessed 2026-09-21
Scope and assumptions

This is a documentation-based design, not a tested connector. The issue-to-task example and failure drills are illustrative.

Exactly-once remote actions depend on the destination’s controls and retention window. Security and recovery need implementation-specific review.

AI-assisted research and editing. Our editorial standards.

Continue reading

Your SaaS Export Is Not an Escape Plan