Webhooks Explained: Don't Call Us, We'll Call You
Deep Dive: Why At-Least-Once Delivery Demands Idempotency
Webhooks let one system push event data to another the moment something happens.
π― System Scenario & Requirements
System Goal
Webhooks let one system push event data to another the moment something happens.
Actors & Components
- Application or API tier
- Core service under design
- Operator or SRE observer
Functional Requirements
- TLDR: Webhooks let one system push event data to another the moment something happens.
- Instead of polling ("anything new?"), you expose an endpoint and the provider POSTs signed event payloads to you in near real-time.
- The key production requirements: signature verification, idempotency, async processing.
Constraints & Assumptions
- Most webhook providers use at-least-once delivery β duplicates are normal, ordering is not guaranteed.
- π Webhook Delivery Sequence The sequence above traces the complete lifecycle of a single webhook event from provider to worker.
β‘ Execution Stages & Decision Trace
Stage 1 β The Basics: HTTP Callbacks and Event-Driven Delivery
A webhook is an HTTP callback.
When a specific event occurs, the event source (provider) sends an HTTP POST request to a URL you specify β your webhook endpoint.
Deep Dive
Scenario context
Webhooks let one system push event data to another the moment something happens. Instead of polling ("anything new?"), you expose an endpoint and the provider POSTs signed event payloads to you in near real-time. The key production requirements: signature verification, idempotency, async processing.
Webhook providers guarantee delivery by retrying on failure β not by ensuring exactly-once. A network timeout afβ¦
This walkthrough focuses on Deep Dive: Why At-Least-Once Delivery Demands Idempotency.
Before making a design choice, clarify:
- Webhook providers guarantee delivery by retrying on failure β not by ensuring exactly-once.
- A network timeout after your handler processes an event but before returning 200 causes the same event to arrive again.
- Idempotency means processing an event twice produces the same result as once.
Concepts in play: api-gateway, event-driven-architecture, stack-and-queue-data-structures, circuit-breaker
Stage 1 β The Basics: HTTP Callbacks and Event-Driven Delivery
- A webhook is an HTTP callback.
- When a specific event occurs, the event source (provider) sends an HTTP POST request to a URL you specify β your webhook endpoint.
- No polling, no long connections.
- The three-step registration flow: 1.
Observable outcome: The three-step registration flow: 1.
Stage 2 β Stop Polling β Let the Provider Ring Your Doorbell
- Polling means your app repeatedly asks a provider "anything new?" β burning bandwidth and adding latency whether or not anything changed.
- Webhooks invert the call: you register a URL, and the provider calls your endpoint the instant an event occurs.
- Analogy: Polling is calling the courier every 5 minutes.
- A webhook is the courier ringing your doorbell the moment the package arrives.
Observable outcome: A webhook is the courier ringing your doorbell the moment the package arrives.
Stage 3 β What a Webhook Payload Looks Like
- Most providers send a structured JSON body over HTTPS POST: Key fields in every real-world webhook: - id β unique event identifier; use for deduplication.
- type β event name; drives routing in your handler.
- created β Unix timestamp; enables replay-window validation.
- data β the event payload; schema varies by event type.
{
"id": "evt_101",
"type": "payment.succeeded",
"created": 1772877602,
"data": {
"transaction_id": "txn_9001",
"amount": 4999,
"currency": "USD"
}
}
Observable outcome: - data β the event payload; schema varies by event type.
Stage 4 β Webhook Delivery Flow
- The complete lifecycle from event to processed business logic: The critical design principle: your endpoint's only job is to acknowledge receipt (return 200) as fast as possible.
- All actual work happens asynchronously.
- This prevents provider retry storms.
- Provider retry schedules (common defaults): Providers consider a delivery successful only when they receive a 2xx response within their timeout window (usually 5β30 seconds).
flowchart TD
A[Event occurs at Provider] --> B[Provider signs payload with HMAC]
B --> C[Provider POSTs to your endpoint over HTTPS]
C --> D{Signature valid?}
D -->|No| E[Return 401 reject]
D -->|Yes| F{Event ID already seen?}
F -->|Yes| G[Return 200 silently ignore]
F -->|No| H[Persist raw payload to DB]
H --> I[Enqueue job for async worker]
I --> J[Return 200 immediately]
J --> K[Worker executes business logic]
K --> L[Mark event as processed]
Observable outcome: Provider retry schedules (common defaults): Providers consider a delivery successful only when they receive a 2xx response within their timeout window (usually 5β30 seconds).
Stage 5 β The Production-Safe Webhook Handler
- A naive endpoint that just processes inline is dangerous: it creates duplicate actions when providers retry.
- The correct pattern has 5 ordered steps: Why return 200 before processing?
- Most providers retry if they don't receive a timely 2xx.
- If your business logic runs inline and takes too long, the same event fires twice.
flowchart TD
A[Provider POST] --> B{Valid HMAC
signature?}
B -->|No| C[Return 401]
B -->|Yes| D{Duplicate
event_id?}
D -->|Yes| E[Return 200 ignore]
D -->|No| F[Persist event
to durable store]
F --> G[Enqueue for async
worker]
G --> H[Return 200 immediately]
H --> I[Worker processes
business logic]
// Node.js / Express β production-safe handler skeleton
app.post('/webhooks/provider', express.raw({ type: 'application/json' }), (req, res) => {
const sig = req.header('X-Signature');
if (!isValidHmac(req.body, sig, process.env.WEBHOOK_SECRET)) {
return res.status(401).send('invalid signature');
}
const event = JSON.parse(req.body.toString('utf8'));
if (isDuplicate(event.id)) {
return res.status(200).send('duplicate ignored');
}
persistEvent(event); // write to DB before ack
enqueueEvent(event); // hand off to async worker
return res.status(200).send('accepted');
});
Observable outcome: If your business logic runs inline and takes too long, the same event fires twice.
Stage 6 β Real-World Applications: Where Webhooks Power Real Systems
Observable outcome: You can explain how βReal-World Applications: Where Webhooks Power Real Systemsβ changes the architecture or implementation path.
End-to-end outcome
Webhook providers guarantee delivery by retrying on failure β not by ensuring exactly-once.
Alternatives considered
Decision Guide: When Webhooks Are (and Aren't) the Answer
Decision Guide: When Webhooks Are (and Aren't) the Answer
Failure and degraded modes
Trade-offs & Failure Modes: Failure Modes You Must Defend Against
- Detection: Most webhook providers use at-least-once delivery β duplicates are normal, ordering is not guaranteed.
- User or operator impact: Most webhook providers use at-least-once delivery β duplicates are normal, ordering is not guaranteed.
