Capabilities/Reliability & Infra

Webhooks

Reliable event delivery to external systems with retry, HMAC verification, and monitoring

webhookseventsHTTPretryHMACintegration

Learning lens

Start with judgment, not a universal prescription.

This page is a learning model for understanding the capability. It does not claim exact production internals, exact costs, or an infinite-scale architecture.

Evidence

Conceptual pattern

0->1 default

Start with a durable queue, clear ownership, retries, and idempotency before building a larger event platform.

Cost drivers

retry amplificationqueue requestsworker runtimedelivery history and logs

Watch for breakpoints

  • -backlog grows during normal traffic
  • -manual recovery becomes frequent
  • -independent consumers need replay

Learn first

Concepts behind this architecture

The Problem

When events happen in your system (payment completed, order shipped, user signed up), external systems need to know. Webhooks push HTTP POST requests to customer-configured URLs when events occur. The challenge: the internet is unreliable. Customer endpoints go down, respond slowly, or return errors. You must ensure delivery with retries, prevent duplicate processing, secure payloads with signatures, and manage thousands of webhook endpoints with wildly varying reliability — all without letting slow endpoints back up your event pipeline.

Architectural Approaches

Synchronous Dispatch with Retry Queue

Attempt delivery immediately when the event occurs. If the endpoint is down or slow, enqueue the webhook for retry. A background worker processes the retry queue with exponential backoff. Simple and low-latency for healthy endpoints.

Pros

  • +Lowest latency for healthy endpoints — near-instant delivery
  • +Simple architecture — direct HTTP call + retry queue
  • +Easy to reason about delivery order

Cons

  • −Slow endpoints block the dispatch thread
  • −Must handle timeouts carefully (5-10 second max)
  • −Synchronous dispatch can overwhelm the event producer under load
  • −Retry queue can grow unbounded if many endpoints are down

Fully Async Queue-Based Dispatch

All webhooks are enqueued immediately, and a fleet of workers processes the queue. Each worker picks a webhook, delivers it, and handles the result (success, retry, or dead-letter). The event producer never blocks on delivery. This is the standard pattern for high-volume webhook systems.

Pros

  • +Event producer is completely decoupled from delivery
  • +Workers can be scaled independently based on queue depth
  • +Natural backpressure — queue absorbs spikes
  • +Easy to add rate limiting per endpoint

Cons

  • −Added latency from queue processing (1-5 seconds typical)
  • −More infrastructure to manage (queue + workers)
  • −Must handle queue ordering carefully for per-endpoint FIFO
  • −Monitoring and observability are more complex

Managed Webhook Service

Use a managed service like Svix, Hookdeck, or AWS EventBridge to handle webhook delivery. Your system publishes events to the service, and it handles endpoint management, delivery, retries, and monitoring.

Pros

  • +Zero infrastructure to manage
  • +Built-in retry, monitoring, and endpoint management UI
  • +Handles edge cases (endpoint rotation, signature verification)
  • +Customer-facing portal for managing webhook subscriptions

Cons

  • −Per-event pricing can be expensive at high volume
  • −Vendor dependency for a critical integration path
  • −Less control over delivery behavior and timing
  • −Data passes through a third party

Architecture

Loading diagram...
Webhooks — High-level architecture

Key Components

Webhook Service

Core orchestrator that receives events from the event bus, resolves which endpoints are subscribed to each event type, generates signed payloads, and enqueues delivery jobs. Handles event filtering (only send “order.completed” events to endpoints subscribed to order events).

Signature Generator

Signs each webhook payload with HMAC-SHA256 using a per-endpoint secret key. The signature is sent in a header (e.g., X-Webhook-Signature). Customers verify the signature to ensure the webhook came from your system and wasn’t tampered with.

Dispatch Workers

Pool of HTTP client workers that deliver webhooks. Each worker sends a POST request with the signed payload, enforces a timeout (5-10 seconds), and records the result. Handles connection pooling, TLS verification, and redirect following (with limits).

Retry Scheduler

Manages failed deliveries with exponential backoff: 1min, 5min, 30min, 2hr, 8hr, 24hr. Tracks attempt count per event. After max attempts (typically 5-8 over 24-72 hours), moves to the dead-letter queue and optionally notifies the endpoint owner.

Endpoint Manager

CRUD API for customers to register, update, and delete webhook endpoints. Stores the URL, subscribed event types, signing secret, and active/paused status. Supports endpoint verification (send a challenge and expect a specific response).

Delivery Dashboard

Customer-facing UI showing delivery history: timestamp, event type, response status code, response time, and payload. Allows customers to inspect failed deliveries, view request/response headers, and manually retry failed events.

Data Model

Loading diagram...
Webhooks — Entity relationship diagram

HMAC Signature Verification

Webhook payloads must be verified by the receiver to ensure authenticity and integrity.

Signing process (your side):

  1. Generate a unique secret per endpoint (32+ random bytes, base64 encoded)
  2. For each delivery, compute: signature = HMAC-SHA256(secret, timestamp + "." + payload_body)
  3. Send headers: X-Webhook-Signature: t=1707100000,v1=abc123... and X-Webhook-Timestamp: 1707100000

Verification process (customer side):

  1. Extract the timestamp and signature from the header
  2. Reject if timestamp is older than 5 minutes (replay protection)
  3. Compute expected signature: HMAC-SHA256(secret, timestamp + "." + raw_body)
  4. Compare with constant-time comparison to prevent timing attacks
  5. If match, process the webhook; if not, return 401

Including the timestamp in the signature prevents replay attacks — an attacker can’t re-send a captured webhook because the timestamp check will fail.

Secret rotation: Support multiple active secrets per endpoint. When rotating, sign with the new secret and include signatures for both old and new secrets in the header. Customers verify against both during the rotation window.

Retry Strategy and Circuit Breaking

Not all failures are equal. The retry strategy should adapt to the failure type.

Retryable failures:

  • Network timeout → retry with exponential backoff
  • 5xx server error → retry (server is temporarily down)
  • Connection refused → retry (server restarting)

Non-retryable failures:

  • 4xx client error (except 429) → don’t retry, the endpoint is misconfigured
  • Invalid URL → don’t retry, notify the customer
  • TLS certificate error → don’t retry, security issue
  • 429 Too Many Requests → retry, but respect the Retry-After header

Retry schedule: 1min → 5min → 30min → 2hr → 8hr → 24hr (6 attempts over ~34 hours). After final failure, move to DLQ.

Circuit breaker per endpoint: If an endpoint fails 10 consecutive deliveries, “open” the circuit — pause all deliveries to that endpoint. Periodically send a “health check” delivery. If it succeeds, close the circuit and resume. This prevents wasting resources on consistently failing endpoints.

Auto-disable: After 72 hours of continuous failures, automatically disable the endpoint and notify the customer via email. Require them to re-enable manually after fixing the issue.

Ordering and Idempotency

Delivery ordering: Webhooks may arrive out of order due to retries and parallel dispatch. If order matters (e.g., order.created must arrive before order.shipped), options:

  • Include a sequence number in the payload. Receivers buffer and reorder.
  • Use per-endpoint FIFO queues (SQS FIFO, or single-worker-per-endpoint). Slower but ordered.
  • Accept out-of-order delivery and include enough state in each event for the receiver to reconcile.

Idempotency: Receivers must handle duplicate deliveries. Include a unique event_id in every webhook. Receivers store processed event IDs and skip duplicates. Your documentation should clearly state that webhooks have at-least-once delivery semantics.

Event payload design:

  • Include the full resource state (“fat events”) so receivers don’t need to call back to your API
  • OR include only the event type and resource ID (“thin events”) and let receivers fetch the current state. Thin events are simpler but require an API call per webhook.
  • Best practice: include the changed fields and the event type. Receivers can process directly or fetch if they need more context.

Versioning: Include an API version in the webhook payload or URL path. When you change the payload schema, maintain backward compatibility or introduce a new version. Customers choose which version they receive.

Real-World Examples

Stripe

Industry-standard webhook implementation. HMAC-SHA256 signatures with timestamp. Retries over 72 hours with exponential backoff. Dashboard showing delivery attempts with full request/response details. Supports multiple webhook endpoints per account with event type filtering.

GitHub

Webhook deliveries for repository events (push, PR, issue). Each delivery logged with request/response. Redeliver button in the UI. Supports both HMAC-SHA256 and HMAC-SHA1 signatures. Ping event sent on endpoint creation for verification.

Shopify

Mandatory webhook verification for apps. Uses HMAC-SHA256 with the app secret. Webhooks are registered per-topic (orders/create, products/update). Automatic removal of endpoints that fail consistently for 19 days.

Svix

Managed webhook service used by companies like Clerk and Liveblocks. Provides SDKs for both sending and receiving. Built-in endpoint management portal that can be embedded in your dashboard. Handles retry, signing, and delivery monitoring.

Architectural Tradeoffs

Fat events (full payload) vs thin events (ID only)

Pros

  • +Fat: receiver doesn't need API callback, lower latency
  • +Thin: smaller payload, always current state (not stale snapshot)
  • +Fat: works even if your API is temporarily down

Cons

  • −Fat: larger payloads, potential data consistency issues if state changes between event and delivery
  • −Thin: requires an API call per webhook, adds load to your API
  • −Fat: harder to handle schema changes without breaking receivers

Self-built vs managed webhook service (Svix)

Pros

  • +Self-built: full control, no per-event cost, data stays internal
  • +Managed: faster to implement, battle-tested delivery infrastructure
  • +Managed: customer-facing portal included

Cons

  • −Self-built: significant engineering effort (3-6 weeks for a solid system)
  • −Managed: per-event pricing, vendor dependency
  • −Self-built: must handle all edge cases (retry, signing, circuit breaking)

Guaranteed ordering vs parallel dispatch

Pros

  • +Ordered: events arrive in logical sequence, simpler receiver logic
  • +Parallel: much higher throughput, lower latency
  • +Parallel with sequence numbers: best throughput, receivers reorder if needed

Cons

  • −Ordered: per-endpoint FIFO limits throughput to one delivery at a time
  • −Parallel: out-of-order delivery, receivers must handle reordering
  • −Sequence numbers: adds complexity to both sender and receiver

Learn Webhooks

Copy a learning context prompt for an AI assistant. It keeps assumptions visible and asks for tradeoffs, cost drivers, failure modes, and what to measure before adding complexity.

Explore More Capabilities