FSD Frontend System Design

Part I β€” The Pipes Β· Lesson 2.6

WebHooks

In one lineServer-to-server push: you register a URL, and the other system calls you when something happens.

Where you've seen itStripe hitting your /webhooks/stripe endpoint the instant a payment settles β€” no browser involved.

  • Time13 min
  • DiagramPolling vs webhook, plus the browser's last mile
  • Chapter2 Β· Communication

Diagram

diagram
WITHOUT WEBHOOKS β€” your server polls someone else's

  Your API ──"paid yet?"──► Stripe    no
  Your API ──"paid yet?"──► Stripe    no
  Your API ──"paid yet?"──► Stripe    YES (30s late)


WITH WEBHOOKS β€” they call you, once, immediately

  Stripe ──POST /webhooks/stripe──► Your API
          { type: "payment_intent.succeeded", ... }
          ◄────── 200 OK (fast, before you do the work) ──
diagram
THE FULL CHAIN β€” webhook ends at your server, not at the user

  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”  webhook   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   SSE/WS/push   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”
  β”‚ Stripe β”‚ ─────────► β”‚ Your API β”‚ ──────────────► β”‚ Browser β”‚
  β””β”€β”€β”€β”€β”€β”€β”€β”€β”˜   POST     β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                 β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                             β”‚
                             └─► queue β†’ email, ledger, fulfilment

  A webhook can never reach a browser directly: browsers have no URL.
diagram
DELIVERY REALITY β€” assume every event arrives twice, or late

  attempt 1  βœ— 500        ┐
  attempt 2  βœ— timeout    β”œβ”€ provider retries with backoff
  attempt 3  βœ“ 200        β”˜
             └── attempt 1 may already have run
                 β‡’ deduplicate by event id

How it works

  1. You register an HTTPS endpoint with the provider and subscribe to event types.
  2. The event fires; the provider POSTs a JSON payload signed with a shared secret.
  3. You verify the signature, then respond 200 immediately.
  4. Do the real work asynchronously on a queue β€” never inside the request.
  5. Deduplicate by event id: delivery is at-least-once, so replays are normal.

Trade-offs

Use whenAvoid when
Another system owns the eventThe event originates in your own UI
Payments, CI, deploys, CRM syncYou need a response back to the caller
Latency matters more than polling costThe receiver has no public URL

Security checklist: verify the HMAC signature, reject stale timestamps (replay protection), allowlist source IPs where published, and never trust payload data without re-fetching from the provider's API for anything money-related.

Interview angle

"Payment succeeds. How does the user's screen update?"

  • Two hops: Stripe β†’ your server by webhook, then your server β†’ the browser by SSE, WebSocket, or a short poll on the order.
  • Never wait on the webhook in the checkout request β€” show an optimistic pending state and reconcile.
  • Handle duplicate and out-of-order deliveries with an idempotency key on the event id.

Recap

  • Webhooks are push between servers; the browser needs a second transport for the last mile.
  • Respond 200 fast, queue the work, verify the signature.
  • At-least-once delivery means idempotency is mandatory, not optional.