To make webhook handling reliable in TypeScript, verify each request using the provider’s documented signature rules, durably record the event under a unique provider-and-event ID, and move business work to a retryable worker. A repeated delivery should be acknowledged only after it is safely stored—not allowed to repeat its business effect. The exact signature format, retry policy and acknowledgment expectations depend on the provider.
What reliability means for a webhook receiver
A webhook can be delivered more than once, and a receiver can fail after accepting a request or while processing it. Design for those cases rather than assuming a single delivery. Idempotency prevents a retry from applying the same effect twice; deduplication identifies a repeated delivery of an event the receiver has already accepted.
As an Amazon Associate I earn from qualifying purchases.
These are related but distinct protections. A provider event ID is usually a useful key for recognizing repeat deliveries of that same event. It may not protect against two different events that request the same real-world action. For that, the business operation may need its own idempotency key or uniqueness rule.
The Tool Desk
Outbyte Driver Updater FREEFix the driver behind crashes, sound loss and screen glitchesFind Drivers →Outbyte PC Repair FREEClear out junk files and repair common Windows errorsFree Scan →How to prevent duplicate webhook events in TypeScript
Use a durable inbox and a unique constraint
Store each accepted event in an inbox table with a unique constraint on (provider, event_id). Include the received time, verification result, payload or protected payload reference, processing state, attempt count and last error. The event ID must be stable according to the provider’s documentation; do not substitute a timestamp or an ID generated by your receiver.
#1 Best Overall
In one database transaction, insert the inbox record and make the event ready for work, or enqueue it through an approach that is transactionally coupled to that insert. If the unique constraint rejects an insert, the same provider event has already been durably accepted. Treat that as a duplicate delivery; do not repeat its business effect.
Keep deduplication records for as long as your recovery and business requirements need them. Deleting them too soon can make an old replay look like a new event. Protect stored payloads as sensitive data and avoid logging secrets or unrestricted payload contents.
Make downstream effects idempotent too
An inbox constraint cannot by itself prevent every duplicate effect. A worker can complete an external action and crash before recording the job as complete. On retry, it may try that action again. Use a business-operation key, a downstream service’s idempotency facility, or a database constraint around the effect where possible. Track completion only after the effect is safely accounted for.
Do these 3 things before closing this tab:
1Fix the driver behind crashes, sound loss and screen glitches2Clear out junk files and repair common Windows errors3Scan for outdated or missing drivers - takes under a minuteRank #2
- HTML CSS Design and Build Web Sites
- Comes with secure packaging
- It can be a gift option
Stripe’s API idempotency keys illustrate safe retries of API requests: Stripe says its API supports idempotency so a request can be retried without accidentally performing the same operation twice (Stripe API: Idempotent requests). This describes Stripe API requests, not a universal guarantee about webhook delivery or a substitute for the receiver’s event inbox. Stripe also says it may prune idempotency keys once they are at least 24 hours old; do not treat that key store as permanent deduplication for your own event processing (Stripe API: Idempotent requests).
How to verify a webhook signature with the raw request body
Verify the signature before trusting or acting on the payload. Use the provider’s documented signing secret, signature format and timestamp rules. For providers that sign the raw request body, verification must use the exact bytes received—not JSON parsed and serialized again. Parsing can change whitespace, key order or encoding, invalidating a signature check.
Configure the framework and middleware path to preserve the raw bytes needed for verification, and validate that behavior in the runtime and deployment route you actually use. The available documentation confirms that Stripe uses a webhook endpoint secret to generate signatures, but does not establish one framework-specific TypeScript middleware recipe. Check the provider’s current instructions for the exact header, raw-body requirements and timestamp tolerance.
Rank #3
Also account for duplicate headers. Node.js documents header-specific duplicate handling, and the joinDuplicateHeaders option changes how some duplicates are represented (Node.js HTTP: message.headers). Confirm how the signature header is exposed by your Node.js version, framework, proxy and deployment path, then follow the provider’s parsing requirements. Do not assume every runtime combines or discards duplicates the same way.
What should happen before the handler returns success?
Keep the HTTP request path short, but do not acknowledge an event before it is durably accepted. Apply a request-size limit, preserve the bytes required for signature verification, verify authenticity, validate the event envelope, and persist the event and its work state. Then return the success response expected by that provider. Do slower business processing asynchronously.
This is an engineering pattern, not a universal acknowledgment deadline or a provider-independent requirement to return a particular status code. Consult the provider’s current delivery documentation for which responses count as success and what delivery or retry behavior follows. A durable queue or transactionally coupled outbox can separate acceptance from worker availability; an in-memory promise or background task alone cannot survive a process crash.
Rank #4
- Brand: Wiley
- Set of 2 Volumes
- A handy two-book set that uniquely combines related technologies Highly visual format and accessible language makes these books highly effective learning tools Perfect for beginning web designers and front-end developers
- Limit and capture: enforce a body-size limit and retain the exact bytes needed by the provider’s signature scheme.
- Authenticate: verify the signature and any required timestamp checks before treating the payload as trusted.
- Validate: check the event envelope and required fields before accepting it for processing.
- Accept durably: insert the event using the provider-and-event uniqueness key and persist or transactionally enqueue its work.
- Acknowledge: return the provider-appropriate success response after durable acceptance, including for a duplicate that is already safely recorded.
- Process asynchronously: let a worker retry transient failures while protecting each business effect from duplication.
Invalid signatures must not create business effects. Avoid logging signing secrets, signature values or unrestricted sensitive payloads. Keep enough protected operational information to investigate failures without turning logs into a second, poorly controlled copy of customer data.
How to retry a failed webhook safely
Separate delivery acceptance from business processing. If an event is durably stored but a downstream dependency is temporarily unavailable, keep it pending or mark the attempt failed with an error and retry it through the worker. Backoff and retry limits should reflect the provider, dependency and business impact; the cited documentation does not establish one schedule that applies to all webhook providers.
Make processing state explicit, for example: pending, processing, failed and completed. Record attempt count and last error, and ensure a worker can reclaim work left in progress after a crash. The state transition and the business effect need careful coordination: a crash can happen between them, which is why downstream idempotency remains necessary.
Best Value
Do not treat every failure alike. A transient timeout may be worth retrying; a permanently invalid event may require investigation or a corrected integration rather than endless attempts. Define the classification and escalation policy for your system, and preserve enough error context to diagnose failures without exposing secrets.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.How to recover after an outage
Make backlog and failure visible
Provide an operational view of accepted, pending, failed and completed events. Alert on the age of the oldest pending item and on repeated failures, not just on whether the webhook endpoint is reachable. A receiver can return success reliably while its worker queue quietly accumulates an unprocessed backlog.
Replay without bypassing deduplication
Support controlled replay from the stored inbox or the provider’s redelivery mechanism. A replay should pass through the same idempotency protections as normal processing; do not delete the original record or invent a new event ID merely to force execution. If an operator needs to repeat a business action intentionally, make that a separate, auditable operation with its own safeguards.
Plan for provider history and event versions
Provider-side event history is not a replacement for local retention. Stripe documents that events can be retrieved through its API for 30 days, and that an event’s data is rendered using the API version in effect when the event was created rather than silently changing to the current version (Stripe API: Events). Retain local records for the period your recovery needs require, and ensure consumers can handle older event shapes or transform them deliberately.
If local records are missing or provider delivery history has expired, reconcile against the provider’s current resource state where that is possible. A current resource snapshot may help restore business state, but it is not necessarily equivalent to replaying every historical event. Design reconciliation as an explicit recovery path and record what it repaired.
Design choices: synchronous work or durable asynchronous acceptance?
| Approach | Response latency | Failure isolation | Operational complexity | Replayability |
|---|---|---|---|---|
| Synchronous business processing in the request | Depends on the full processing path; slow work delays the response. | A downstream failure can prevent successful handling of the delivery. | Fewer moving parts, but request handling must coordinate all work. | Requires a separate mechanism to record and replay failed work. |
| Durable acceptance followed by asynchronous processing | Usually limited to validation and durable storage; no universal response-time figure is established. | Worker or dependency failures can be handled after acceptance. | Requires durable work coordination, worker monitoring and recovery controls. | Stored inbox state can support controlled retry and replay. |
These are architectural trade-offs, not measured benchmarks. For events where losing accepted work would be costly, durable acceptance gives the receiver a clear point at which it owns recovery. Keep the acknowledgment behavior aligned with the provider’s requirements.
Quick Recap
Implementation checklist
- Confirm the provider’s current signing, timestamp, response, retry, manual-redelivery and retention rules.
- Preserve the exact bytes required by signature verification and verify before trusting the payload.
- Limit request size and protect secrets and payload data in logs and storage.
- Store a stable provider event ID under a database uniqueness constraint.
- Couple inbox insertion to durable work creation; acknowledge only after durable acceptance.
- Make downstream business mutations safe to repeat, including after a crash between effect and completion recording.
- Track processing state, attempts and errors; monitor pending age and repeated failures.
- Retain enough data for recovery, handle historical event versions, and keep replay subject to the same deduplication controls.
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.




