Handling Webhooks Safely

Treat every inbound webhook as hostile: verify, dedupe, ack fast, process async, re-read the truth

Handling Webhooks Safely Treat every inbound webhook as hostile: verify, dedupe, ack fast, process async, re-read the truth POST webhook event Endpoint verifies the HMAC signature first; a bad signature is rejected before any work. seen this event id? new / drop if replay 200 ACK (fast) enqueue for async work deliver event read authoritative state The webhook is only a hint; the handler reads current truth and applies it idempotently. current truth Verify + dedupe Ack fast + enqueue Process + reconcile Payment rail · webhook sender · Sequence participant Payment rail webhook sender Webhook edge · verify + ack · Sequence participant Webhook edge verify + ack Dedupe store · seen event ids · Sequence participant Dedupe store seen event ids Worker queue · durable work · Sequence participant Worker queue durable work Async worker · idempotent · Sequence participant Async worker idempotent Rail API · source of truth · Sequence participant Rail API source of truth Legend request return security async trace

Guard at the Edge

  • • Reject any event whose HMAC signature fails
  • • Check the dedupe store so replays are dropped once
  • • No business logic runs before both checks pass

Acknowledge, Then Work

  • • Return 200 fast so the rail stops retrying
  • • Hand the event to a durable queue, not the request thread
  • • The endpoint owns nothing slow

Trust the Source, Not the Payload

  • • The worker re-reads authoritative state from the rail API
  • • The webhook is only a hint that something changed
  • • Handlers apply idempotently so re-delivery is safe