Unlimited Design & Technology

APIs and Integration

Design webhook consumers for retries and duplicates

Webhook delivery is not the same as business completion. Build a receiving path that authenticates messages, records durable work, and handles repeated or out-of-order events without silently losing actions.

UDT InsightsOct 8, 2020
A colleague routes webhook deliveries and a retry loop through a checked queue. A seated operator uses a laptop.

A webhook lets another system notify your application when something changes. That convenience moves operational work into your receiving service. Before connecting a business workflow, decide what a successful acknowledgment means and how the team will recover messages that fail after receipt.

Start with the sender’s actual guarantees

Read the provider contract rather than assuming every webhook behaves alike. Stripe documents possible duplicate deliveries and does not guarantee event delivery order.[4] These properties explain why its consumers need duplicate detection and an ordering strategy. Another sender may define different identifiers, retry windows, or acknowledgment rules.

Keep event identity separate from business identity. A repeated delivery of one event is different from two events that concern the same invoice. Record both identifiers where available. Define whether an event represents a historical change or a notification to retrieve current state.

Separate receipt from business execution

Stripe recommends a quick successful response before complex logic and requires the raw request body for signature verification.[4] For your design, verify authenticity first, then durably record the event or enqueue work before acknowledging acceptance. If durable storage fails, do not claim that you accepted the work.

Use a worker to apply business changes. Recommend an atomic local transition that records completion with the relevant deduplication identity. A worker can crash after calling an external system, so the downstream action also needs a recovery or idempotency strategy. A queue alone does not solve that uncertainty.

Make replay an operational capability

A failed event should be visible without exposing its entire payload to everyone. Give authorized operators a reason, attempt history, and controlled replay action. Define when they should retrieve fresh provider state instead of repeating an old transition.

Give replay actions an audit trail. Operators should know who requested another attempt, which event it concerns, and whether the replay can create an external side effect. Do not grant replay permission merely because someone can view failures.

  • Validate the sender signature using its documented procedure.
  • Persist the provider, event identifier, receipt time, and processing state.
  • Test duplicate, delayed, reversed, and concurrently delivered events.
  • Route exhausted failures to a review queue with a named owner.

Hypothetical example: a subscription entitlement

Hypothetical example: a learning platform receives a subscription change event before an earlier creation event. The worker retrieves the current subscription state and updates access according to that state, rather than trusting arrival order. A repeated event produces no additional entitlement.

This approach adds a provider lookup and can encounter provider downtime. The platform keeps the event pending and displays its processing delay to support staff. For workflows that require every historical transition, current-state retrieval alone is insufficient. Choose that distinction before implementation, then demonstrate recovery from a worker crash during an access update.

References

Discuss your next project

Talk with UDT about your needs and the next practical step.

Contact UDT
Zalo