Webhook idempotency without guesswork
Published March 2025 · Naledi Khumalo
Vendors retry webhooks when your endpoint times out or returns 5xx. Some also assign a new delivery ID on each attempt while the business payload stays identical. If you key idempotency only on the delivery ID, you will double-charge, double-ship, or double-email.
Prefer vendor business keys
Look for payment intent IDs, order references, or shipment tracking numbers in the body. Store processed keys in a table with a TTL longer than the vendor’s documented retry window—often 72 hours, but verify in their docs.
When no stable key exists
Hash a canonical JSON representation of fields that define the business event, excluding timestamps and delivery metadata. Document the canonicalisation rules in your handler so the next engineer does not “fix” whitespace and break deduplication.
Respond quickly
Acknowledge with 2xx after the event is persisted to your queue, not after all downstream work finishes. Process asynchronously so retries do not stack during slow database migrations.
Need a second pair of eyes on your handlers? Book an integration review.