What Is Webhook-Based Integration?

What Is Webhook-Based Integration?

A complete, beginner-to-advanced guide to how systems talk to each other in real time — with history, architecture, internal mechanics, Java code, production concerns, and hard-won lessons from Stripe, GitHub, Shopify, Slack, Twilio and Zapier.

01
Introduction & History

Give Me A URL, And I’ll Ring You The Instant Something Happens

Imagine you order a pizza. Instead of calling the restaurant every five minutes to ask “is it ready yet?”, you give them your phone number, and they call you the moment it is out of the oven. That is the entire idea behind a webhook.

Rather than one system constantly pestering another with “anything new? anything new? anything new?”, the second system simply says: “Give me a URL, and I’ll ring you the instant something happens.”

A webhook-based integration is a way for two software systems to communicate where one system (the “producer” or “source”) sends an automatic HTTP message to another system (the “consumer” or “receiver”) the moment a specific event occurs — a payment succeeding, a file being uploaded, a new commit being pushed, a support ticket being closed, and so on.

Where did webhooks come from?

The term “webhook” was coined around 2007 by Jeff Lindsay, a developer who was inspired by the general programming concept of a “hook” — a piece of code that lets you plug custom behaviour into an existing system at a specific point, without modifying that system’s source code. Think of a hook like a coat hook on a wall: the wall (the existing system) does not change, but you can hang something new on it (your custom logic) whenever you like.

Before webhooks became common, most systems that needed near-real-time updates used a technique called polling — repeatedly asking “anything new?” on a timer. Polling worked, but it wasted bandwidth, added delay, and did not scale well when thousands of clients all wanted updates. As the web matured and more services exposed APIs (PayPal, Twitter, GitHub, Stripe), the industry gradually adopted webhooks as the default way to push events outward instead of making everyone poll for them.

1

Early 2000s — The Hook Concept

Developers use “hooks” inside frameworks (like Git hooks or WordPress hooks) to run custom code at specific lifecycle points, but only within a single application.

2

2007 — The Term “Webhook” is Coined

Jeff Lindsay proposes extending the hook idea across the network using plain HTTP callbacks — a “web hook.”

3

2008–2012 — Early Adopters

PayPal (IPN), GitHub, and various early SaaS platforms begin using HTTP callbacks to notify external servers about payments, commits, and pushes.

4

2013–2018 — Mainstream Era

Stripe, Slack, Shopify, Twilio, and Zapier build entire integration ecosystems around webhooks, making them a standard tool for any SaaS API.

5

2019–Present — Standardisation

Efforts like the CloudEvents specification (from the CNCF) and standards bodies push toward consistent webhook payload formats, signing schemes, and retry semantics across the industry.

Everyday analogy

A webhook is the software equivalent of leaving your number with the barista instead of standing at the counter watching your drink get made. You are free to do other things, and the moment your coffee is ready, they call your name — no wasted attention on either side.

02
Problem & Motivation

Polling Is Slow, Wasteful, And Does Not Scale

To understand why webhooks matter, picture two ways of finding out if your friend has arrived at the coffee shop — the polling way, and the webhook way.

✗ Polling (“Are you here yet?”)

  • You text your friend every 30 seconds: “Here yet? Here yet? Here yet?”
  • Wastes your friend’s attention (and your phone’s battery).
  • You still have up to a 30-second delay before you find out.
  • If 10,000 people did this to one friend, their phone would melt.

✓ Webhook (“Text me when you arrive”)

  • You give your friend your number once.
  • They text you the instant they arrive — zero wasted messages.
  • Near-instant notification, no polling delay.
  • Scales to any number of “friends” without extra chatter.

In software terms, without webhooks a system that needs to know “has this payment gone through yet?” has two bad options: hammer the payment provider’s API every few seconds (polling — wasteful, slow, and costly at scale), or make the user wait on a page doing nothing until something times out. Webhooks solve this by inverting the relationship: the source system pushes data out the instant something happens, and the receiving system just needs one endpoint sitting there, ready to listen.

i
Real-world motivation

Stripe processes millions of payments a day. If every merchant’s server had to poll “did my payment succeed?” every second, Stripe’s API would collapse under load. Instead, Stripe fires a webhook the moment a payment’s status changes, and merchants just wait for the call.

What the shift really buys you

The move from polling to webhooks is not just a small performance tweak — it changes what an integration is actually good for. Polling caps how fresh your data can be at the poll interval, and gets more expensive the fresher you want it. Webhooks decouple freshness from cost entirely: whether a source system emits one event a day or ten thousand events a second, your receiver only does work when there is real work to do.

03
Core Concepts

The Vocabulary You Will See In Every Webhook Doc

Before going deeper, let us define the vocabulary you will see throughout this guide, explained in plain language.

Ev

Event

Something that happened — order.created, payment.failed, user.signed_up. The trigger for a webhook.

Pr

Producer / Source

The system that detects the event and sends the webhook (e.g., Stripe, GitHub, Shopify).

Cn

Consumer / Receiver

Your server — the one that owns the endpoint URL and reacts to incoming webhook calls.

Ep

Endpoint

A specific URL on your server (like https://yourapp.com/webhooks/stripe) that is ready to accept incoming HTTP POST requests.

Pl

Payload

The actual data sent in the webhook — usually a JSON document describing what happened.

Sb

Subscription / Registration

The act of telling the producer “send events of type X to this URL.” Usually done once, via a dashboard or API call.

Sg

Signature / Secret

A cryptographic stamp the producer attaches to prove the webhook really came from them and was not tampered with.

Rt

Retry / Redelivery

If your endpoint does not respond correctly, the producer tries sending the webhook again later.

Id

Idempotency

Designing your receiver so that processing the same event twice causes no harm — critical since retries can duplicate delivery.

Webhooks vs. APIs vs. Polling — what’s the difference?

ApproachWho initiates?LatencyServer loadAnalogy
Traditional API (pull)You (the client) askDepends on how often you askHigh if you ask oftenYou calling the restaurant repeatedly.
PollingYou, on a timerUp to one poll intervalWasteful — most calls return “nothing new”Calling every 5 minutes “is it ready?”
Webhook (push)The source system, when something happensNear-instantMinimal — only real events sentThey call you when it’s ready.
WebSocket / streamingEither side, over a persistent connectionInstantHigher (connection stays open)Staying on the phone line together.

Webhooks sit in a sweet spot: they are far more efficient than polling, but far simpler to build and operate than maintaining persistent WebSocket connections for every integration.

04
Architecture & Components

A Small Number Of Moving Parts, Each One Matters

A webhook integration has a small number of moving parts, but each one matters. Let us walk through the architecture.

01

Event Source

The internal system component (e.g., an order-processing service) that detects a state change worth notifying about.

02

Event Publisher / Dispatcher

Packages the event into a payload, looks up which subscribers care about it, and sends the HTTP request(s).

03

Delivery Queue

A message queue (like Kafka, SQS, or RabbitMQ) that buffers events so a burst of activity does not overwhelm delivery workers.

04

Subscription Registry

A database table mapping “customer X wants event type Y delivered to URL Z.”

05

Receiver Endpoint

Your HTTP server, listening for POST requests, verifying signatures, and processing payloads.

06

Retry Engine

Tracks failed deliveries and retries them with backoff, eventually giving up and logging a dead letter.

Event Sourcee.g. Order ServiceEvent Publisherfan-out + subscribe lookupDelivery QueueKafka / SQS / RMQDelivery WorkerHTTPS POST + signature2xx = deliveredYour Receiver/webhooks/*RetryBACKOFFRETRY LOOPDead LetterMAX RETRIESThree failure paths converge on a queue: instant success, retry with backoff, or dead-letter for humans.
Fig 1 · High-level webhook architecture — queue between source and dispatch, retries close to the failure, dead-letter as the safety net.

Reading the diagram: an event happens inside the source system (like a new order). The publisher looks up who is subscribed to order.created events and pushes a message onto a queue. A pool of delivery workers pulls messages off that queue and makes the actual HTTP POST call to your registered URL, attaching a cryptographic signature. If your server responds with a success code (2xx), the delivery is marked complete. If it fails or times out, the retry engine schedules another attempt later — and if it keeps failing, the event eventually lands in a “dead letter” log so a human can investigate.

Why a queue in the middle?

Without a queue, a spike in events (say, a flash sale causing 50,000 orders in one minute) would try to fire 50,000 webhook calls instantly, overwhelming both the sender’s outbound capacity and the receiver’s inbound capacity. A queue smooths this into a manageable, controlled flow.

05
Internal Working

What Actually Happens On The Wire

Let us trace exactly what happens, step by step, when a customer completes a purchase and your application needs to know about it via a webhook from a payment provider.

1

State change occurs

The payment provider’s internal ledger updates: a charge moves from “pending” to “succeeded.”

2

Event object is created

An internal event record is generated, usually with a unique event ID, a timestamp, an event type string (e.g. payment_intent.succeeded), and a snapshot of the relevant data.

3

Subscribers are looked up

The publisher queries its subscription registry: “which endpoints want payment_intent.succeeded events for this account?”

4

Payload is serialised

The event is converted into JSON (or occasionally XML / Protobuf) matching an agreed schema.

5

Signature is computed

A cryptographic HMAC signature is generated using a shared secret key so the receiver can later verify authenticity.

6

HTTP POST is dispatched

The payload is sent to your registered URL, typically with headers like X-Signature, X-Event-Id, and Content-Type: application/json.

7

Receiver responds

Your server verifies the signature, processes (or queues) the event, and responds quickly — ideally within a few seconds — with an HTTP 200.

8

Delivery is confirmed or retried

If no 2xx response arrives within a timeout window, the sender schedules a retry using exponential backoff.

Source SystemQueueDelivery WorkerYour Endpointpublish event (payment_intent.succeeded)dequeue eventserialize payload +compute HMAC signaturePOST /webhooks/stripe (payload + sig header)verify signatureenqueue internal job (async)200 OK — fast ackmark event deliveredbackground worker processesthe queued event later
Fig 2 · A single delivery — verify, queue, ack fast, then process asynchronously.

A minimal Java receiver endpoint

Here is a simplified webhook receiver written using plain Java with the built-in HTTP server, showing signature verification and fast acknowledgment.

Java · minimal signed webhook receiver
import com.sun.net.httpserver.HttpServer;
import com.sun.net.httpserver.HttpExchange;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.net.InetSocketAddress;
import java.nio.charset.StandardCharsets;
import java.util.Base64;

public class WebhookReceiver {

    private static final String SECRET = "whsec_5f8a...replace_with_real_secret";

    public static void main(String[] args) throws Exception {
        HttpServer server = HttpServer.create(new InetSocketAddress(8080), 0);
        server.createContext("/webhooks/payments", WebhookReceiver::handle);
        server.setExecutor(null);
        server.start();
        System.out.println("Webhook receiver listening on port 8080");
    }

    private static void handle(HttpExchange exchange) throws java.io.IOException {
        if (!"POST".equals(exchange.getRequestMethod())) {
            exchange.sendResponseHeaders(405, -1);
            return;
        }

        byte[] rawBody = exchange.getRequestBody().readAllBytes();
        String body = new String(rawBody, StandardCharsets.UTF_8);
        String signatureHeader = exchange.getRequestHeaders().getFirst("X-Signature");

        if (signatureHeader == null || !isValidSignature(body, signatureHeader)) {
            exchange.sendResponseHeaders(401, -1);
            exchange.close();
            return;
        }

        // Acknowledge immediately, process asynchronously
        EventQueue.enqueueForProcessing(body);

        String response = "{\"status\":\"received\"}";
        exchange.sendResponseHeaders(200, response.length());
        exchange.getResponseBody().write(response.getBytes(StandardCharsets.UTF_8));
        exchange.close();
    }

    private static boolean isValidSignature(String payload, String receivedSignature) {
        try {
            Mac mac = Mac.getInstance("HmacSHA256");
            mac.init(new SecretKeySpec(SECRET.getBytes(StandardCharsets.UTF_8), "HmacSHA256"));
            byte[] computed = mac.doFinal(payload.getBytes(StandardCharsets.UTF_8));
            String computedHex = Base64.getEncoder().encodeToString(computed);
            return constantTimeEquals(computedHex, receivedSignature);
        } catch (Exception e) {
            return false;
        }
    }

    // Prevents timing attacks by comparing every byte regardless of an early mismatch
    private static boolean constantTimeEquals(String a, String b) {
        if (a.length() != b.length()) return false;
        int result = 0;
        for (int i = 0; i < a.length(); i++) {
            result |= a.charAt(i) ^ b.charAt(i);
        }
        return result == 0;
    }
}
!
Why respond fast, then process later?

Most webhook providers expect a response within a few seconds (often 5–15s) or they treat the delivery as failed and retry it. If your handler does slow work — sending emails, calling other APIs, updating multiple database tables — do that in a background job. Acknowledge receipt first, process second.

06
Data Flow & Lifecycle

Every Event Walks A Predictable Path From Birth To Terminal State

Every webhook event moves through a predictable lifecycle from birth to (hopefully) successful processing. Understanding this lifecycle helps you design a receiver that is resilient rather than fragile.

1

Trigger

A business event occurs inside the source system (a status change, a new record, a threshold crossed).

2

Serialisation

The event is turned into a structured payload — almost always JSON today.

3

Dispatch

An HTTP POST is sent to every subscribed endpoint, often in parallel across many customers.

4

Receipt & Verification

The receiver validates the signature and checks it has not already processed this exact event ID.

5

Acknowledgment

The receiver returns 2xx quickly, telling the sender “got it, don’t resend.”

6

Processing

The receiver (often asynchronously) updates its own database, triggers side effects, or notifies other services.

7

Terminal state

The event is marked delivered-and-processed on both sides, or, after repeated failures, moved to a dead-letter queue for manual review.

Pendingworker picks upDelivering2xxDeliveredtimeout / non-2xxFailedretry (attempts < max)Dead-LetteredMAX RETRIES
Fig 3 · Every event walks this state machine — the only terminal states are Delivered or DeadLettered.
07
Advantages, Disadvantages & Trade-offs

Real-Time Notifications, Idempotency Homework

Webhooks trade a small amount of receiver-side engineering (signature verification, idempotency, resilience) for a large improvement in real-time responsiveness and decoupling.

✓ Advantages

  • Near real-time notifications, no polling delay.
  • Dramatically reduces unnecessary API traffic.
  • Simple to implement — just an HTTP endpoint.
  • Decouples systems — sender does not need to know how receiver processes data.
  • Scales naturally with event volume, not client count.

⚠ Disadvantages

  • Receiver must be publicly reachable (a challenge behind firewalls / NAT).
  • No built-in guarantee of delivery order.
  • Duplicate deliveries are common — receivers must be idempotent.
  • Debugging is harder — the “client” is a remote system you do not control.
  • Requires careful security (signature verification, replay protection).
  • If your endpoint is down, events can be delayed or lost depending on retry policy.

Webhooks vs. alternatives — when to use what

ScenarioBest ChoiceWhy
Third-party notifies your backend about async events (payments, shipping)WebhookSimple, standard, no persistent connection needed.
Browser needs live updates (chat, live scores)WebSocket / SSENeeds a continuously open channel to push to a UI.
You need guaranteed ordered processing across services internallyMessage queue (Kafka)Provides ordering, replay, and consumer groups that raw webhooks lack.
Client wants data on-demand, not driven by eventsREST / GraphQL APIPull model fits request/response use cases better.
“Webhooks are the ‘call me back’ button of the internet — boring, standard, and quietly powering most of the SaaS you use every day.”
08
Performance & Scalability

Ack Fast, Process Slow

At small scale, webhooks are trivial. At large scale — think thousands of merchants, millions of events per day — several performance considerations become critical.

<15s
typical delivery timeout window
3–8×
typical retry attempts before dead-lettering
2xx
only acceptable “success” response range
~1–5s
recommended handler ack time

Techniques for scaling webhook delivery

  • Queue-based fan-out: use a message broker (Kafka, SQS) between the event source and the HTTP dispatchers so bursts do not overload delivery capacity.
  • Parallel delivery workers: run a pool of stateless worker processes that each pull from the queue and make outbound HTTP calls concurrently.
  • Per-endpoint rate limiting: cap how fast you send to any single receiver so a slow customer endpoint does not back up the whole queue.
  • Batching (where supported): some systems batch multiple events into a single payload to cut HTTP overhead, at the cost of slightly higher latency.
  • Connection pooling & keep-alive: reuse HTTP connections to the same receiver to avoid TLS handshake overhead on every event.

On the receiving side, the golden rule is: acknowledge fast, process slow. A receiver that does heavy synchronous work inside the webhook handler will start timing out under load, triggering unnecessary retries and duplicate processing.

i
Analogy

Think of your webhook endpoint like a restaurant host stand. The host’s only job is to say “table for two, got it, please wait here” — fast. The host does not personally cook the meal while you stand at the door; that work happens in the kitchen (a background job) while the host moves on to greet the next guest.

Scaling on the receiving side

A well-designed receiver treats each incoming request as an isolated unit: verify the signature, drop the payload onto an internal queue (Redis, SQS, in-memory buffer, whatever fits), and return 200. Because that handler does almost no work, one modest instance can absorb thousands of requests per second, and horizontal scaling behind a load balancer is essentially trivial. All the real work — database writes, downstream API calls, email sends — is done by a separate pool of background workers that pull from the internal queue at their own pace.

09
High Availability & Reliability

Fire-And-Forget Over An Unreliable Network

Because webhooks are “fire and forget” over an unreliable network, both the sender and receiver need strategies to survive failure.

Retry strategy with exponential backoff

Most mature webhook systems retry failed deliveries using exponential backoff: wait 1 minute, then 5, then 30, then a few hours, up to a maximum number of attempts (often over 24–72 hours) before giving up.

Java · exponential backoff with jitter
public long computeBackoffMillis(int attempt) {
    long baseMillis = 60_000L; // 1 minute
    long maxMillis = 6 * 60 * 60 * 1000L; // 6 hours cap
    long delay = (long) (baseMillis * Math.pow(2, attempt));
    long jitter = (long) (Math.random() * 1000); // avoid thundering herd
    return Math.min(delay + jitter, maxMillis);
}

Receiver-side resilience checklist

Ik

Idempotency keys

Store processed event IDs so a duplicate delivery is a no-op, not a double-charge or double-email.

Dl

Dead letter queue

Route events that repeatedly fail processing into a separate queue for manual inspection instead of silently dropping them.

Hc

Health checks

Monitor your endpoint’s uptime so you notice outages before your webhook provider’s retries run out.

Gd

Graceful degradation

If a downstream dependency is down, still return 200 quickly and queue the event for later reprocessing.

Handling missed events entirely — the reconciliation pattern

No matter how good the retry logic is, webhooks can theoretically be lost (network partitions, prolonged outages exceeding max retries). Mature integrations pair webhooks with a periodic reconciliation job — a scheduled task that queries the source system’s API directly (“give me everything that changed in the last hour”) to catch anything the webhook stream might have missed.

!
Don’t rely on webhooks alone for anything financially critical

For payments in particular, always keep a nightly (or hourly) reconciliation job that cross-checks your database against the provider’s source-of-truth API.

10
Security

A Door You Leave Open To The Internet On Purpose

Because a webhook endpoint is a public URL accepting POST requests from the internet, it is a natural target. Treat it with the same care as any other public API.

Key protections

  • Signature verification (HMAC): verify every incoming payload against a shared secret before trusting it — shown in the Java example above.
  • HTTPS only: never accept webhook traffic over plain HTTP; it exposes payloads and signatures to interception.
  • Replay protection: include and check a timestamp header, rejecting requests older than a few minutes, to prevent an attacker from resending a captured request later.
  • IP allow-listing (where feasible): some providers publish a fixed set of sending IP ranges you can restrict inbound traffic to, as a secondary layer beyond signatures.
  • Least-privilege processing: your handler should only be able to act within the specific scope implied by the event — do not give the webhook path broad admin privileges.
  • Input validation: never trust the payload shape blindly; validate types and required fields before using them.
“A webhook endpoint is a door you leave open to the internet on purpose. Signature verification is the lock — never skip it, even in a rush to ship.”

Constant-time comparison

Notice in the Java example earlier that signature comparison uses a constant-time loop (constantTimeEquals) instead of String.equals(). This defends against timing attacks, where an attacker measures tiny differences in response time to guess a secret byte by byte.

11
Monitoring, Logging & Metrics

Webhooks Fail Silently If You Are Not Watching

Webhook systems fail silently if you are not watching. Here is what mature teams track on both the sending and receiving side.

Sr

Delivery success rate

Percentage of webhook deliveries that succeed on first attempt vs. require retries.

Lt

End-to-end latency

Time from event creation to successful receiver acknowledgment.

Dl

Retry / dead-letter counts

Volume of events landing in the dead letter queue — a spike here signals a receiver-side problem.

Sg

Signature failure rate

Unexpected spikes could mean a misconfigured secret or an attempted attack.

Rt

Endpoint response time

Slow receiver responses risk timeouts and unnecessary retries under load.

Du

Duplicate event rate

How often the same event ID arrives more than once — validates your idempotency logic is actually needed and working.

On the receiver, structured logging (with the event ID, event type, and processing outcome on every log line) makes it possible to trace a single event’s journey through your system when a customer reports “I never got my confirmation email.”

Tooling tip

Most mature providers (Stripe, GitHub, Shopify) offer a dashboard showing delivery history per endpoint, including response codes and payloads for each attempt — invaluable for debugging without needing your own logs.

12
Deployment & Cloud

Reachable From The Public Internet, Reliably

Deploying a webhook receiver introduces a few concerns beyond a typical internal service, since it must be reachable from the public internet reliably.

  • Public endpoint with TLS: deploy behind a load balancer or API gateway that terminates HTTPS and forwards traffic to your service instances.
  • Local development tunnels: tools like ngrok or cloud-provided dev tunnels let you receive real webhooks on your laptop during development, since providers cannot reach localhost directly.
  • Auto-scaling receivers: since webhook traffic can spike (e.g., a flash sale), your receiver tier should scale horizontally behind a load balancer.
  • Separate ingestion from processing: deploy a lightweight “ingest” service that only verifies and queues events, decoupled from the heavier “processing” service — so a slow downstream dependency never blocks webhook acknowledgment.
  • Blue/green or canary deploys: because a webhook provider may retry against a briefly-unavailable endpoint during a deploy, ensure zero-downtime deployment strategies so you do not manufacture unnecessary retries.
Webhook ProviderStripe / GitHub / …Load BalancerTLS terminationIngest Instance 1verify + queueIngest Instance 2verify + queueMessage QueueKafka / SQSProcessingWorker 1ProcessingWorker 2Databasesource of truth
Fig 4 · Split ingest from processing — a slow downstream never blocks webhook acknowledgment.
13
Databases, Caching & Load Balancing

Idempotency Lives In A Table, Not In Memory

Webhook infrastructure leans heavily on a small set of well-designed database tables. Get these right and idempotency, replay and debugging almost take care of themselves.

Database considerations

  • Event log table: store every received event ID, type, timestamp, and processing status — this is your source of truth for idempotency checks and debugging.
  • Unique constraint on event ID: a database-level unique index on event_id is the simplest, most reliable idempotency guard — a duplicate insert simply fails harmlessly.
  • Subscription registry: on the sending side, store subscriber URLs, secrets, and event type filters in a normalised table for fast lookups during fan-out.
SQL · minimal webhook event log
CREATE TABLE webhook_events (
    event_id      VARCHAR(64) PRIMARY KEY,
    event_type    VARCHAR(100) NOT NULL,
    received_at   TIMESTAMP NOT NULL DEFAULT now(),
    status        VARCHAR(20) NOT NULL DEFAULT 'PENDING',
    payload       JSONB NOT NULL,
    processed_at  TIMESTAMP NULL
);

Caching

Caching plays a smaller but real role: subscription lookups (who wants this event type?) are read far more often than they change, so caching the subscription registry in memory (or Redis) avoids a database round-trip on every single event dispatch.

Load balancing

On the receiving side, a standard load balancer distributes inbound webhook POSTs across multiple receiver instances. Because webhook calls are independent, stateless HTTP requests, this fits typical round-robin or least-connections load balancing without special affinity requirements — as long as your idempotency logic lives in a shared database, not in-memory on a single instance.

14
APIs & Microservices

A Natural Fit For Loosely-Coupled Services

Webhooks are a natural fit for microservice architectures, since they let independently-deployed services notify each other without tight coupling.

Webhook management APIs

Most platforms expose a small REST API for managing webhook subscriptions alongside the webhooks themselves:

REST · typical webhook management endpoints
POST /v1/webhook-endpoints
{
  "url": "https://yourapp.com/webhooks/payments",
  "enabled_events": ["payment_intent.succeeded", "payment_intent.failed"]
}

GET    /v1/webhook-endpoints/{id}
DELETE /v1/webhook-endpoints/{id}
GET    /v1/webhook-endpoints/{id}/deliveries

Webhooks inside a microservices architecture

Internally, many companies use the same webhook pattern between their own microservices — an “Order Service” might fire an internal webhook-style event to a “Shipping Service” and an “Email Service” simultaneously, rather than calling each directly. This is sometimes implemented as literal HTTP webhooks, but more often as messages on an internal event bus (Kafka, RabbitMQ) using the same conceptual pattern with stronger delivery guarantees.

i
External vs internal events

External-facing webhooks (to third-party customers) usually use plain HTTP with signatures. Internal service-to-service events usually use a message broker for stronger ordering and delivery guarantees, since you control both ends.

15
Design Patterns & Anti-patterns

The Patterns That Work — And The Ones That Bite

A handful of webhook-adjacent patterns keep showing up because they answer recurring problems well — and a handful of anti-patterns keep showing up in post-mortems because they ignore those same problems.

Recommended patterns

Fa

Fast-ack, async-process

Verify + queue in the handler; do real work in a background worker.

Ik

Idempotency key store

Persist processed event IDs to safely ignore duplicates.

Dl

Dead letter queue

Never silently drop events that repeatedly fail — route them for review.

Rc

Reconciliation job

Periodically double-check state via API as a safety net against missed events.

Vp

Versioned payloads

Include a schema / API version in every payload so consumers can evolve safely.

Anti-patterns to avoid

Anti-patterns

  • Synchronous heavy processing: doing slow work directly in the handler, causing timeouts and duplicate retries.
  • Trusting unsigned payloads: skipping signature verification “just for now” — a common source of real breaches.
  • Assuming ordered delivery: processing events assuming they arrive in the order they were sent — network retries can reorder them.
  • No idempotency: treating every delivery as guaranteed-once, leading to duplicate charges or duplicate emails.
  • Single point of failure endpoint: running the receiver as a single unscaled instance with no failover.

Instead, aim for

  • Handlers that verify, queue, ack — and nothing else on the hot path.
  • Signature verification treated as non-negotiable, from day one.
  • Explicit ordering guarantees only where you actually need them (usually you don’t).
  • A database-enforced idempotency key on every write triggered by an event.
  • Multiple stateless receiver instances behind a load balancer, everywhere.
16
Best Practices & Common Mistakes

A Portable Checklist For Production Integrations

A short, portable checklist for shipping a webhook integration you will still trust in six months — plus the mistakes that most commonly land teams in a war room.

Best practices checklist

  • Always verify signatures using constant-time comparison.
  • Respond with 2xx within a few seconds; process heavy work asynchronously.
  • Store and check event IDs to guarantee idempotent processing.
  • Log every event’s lifecycle (received → verified → processed) for debuggability.
  • Implement a dead letter queue and alerting on it.
  • Run a periodic reconciliation job for critical data (payments, inventory).
  • Version your payload schema and tolerate unknown fields gracefully.
  • Rotate signing secrets periodically and support graceful secret rollover.

Common mistakes

!
Mistake: treating a 200 response as “fully processed”

A 200 should mean “I have safely queued this and will process it,” not “I have finished all downstream work.” Conflating the two leads to either slow acknowledgments (timeouts) or false confidence when async processing later fails silently.

!
Mistake: ignoring retry storms

If your endpoint goes down for an hour, dozens of providers may all retry simultaneously once it comes back — a “thundering herd.” Make sure your infrastructure can absorb a burst of backlog deliveries without falling over again.

17
Real-World & Industry Examples

How The Biggest Platforms Actually Use Webhooks

Almost every SaaS product you interact with in a day is quietly held together by webhooks. A tour of the most instructive examples:

St

Stripe

Fires events like payment_intent.succeeded with HMAC-SHA256 signatures, exponential backoff retries over 3 days, and a dashboard showing every delivery attempt.

Gh

GitHub

Sends repository events (push, pull_request, issues) to configured webhook URLs, signed with HMAC-SHA1 / SHA256, used heavily to trigger CI / CD pipelines.

Sh

Shopify

Uses webhooks for order and inventory events; enforces strict response-time limits and automatically disables endpoints that fail repeatedly.

Sl

Slack

Uses “Event Subscriptions” (a webhook variant) to notify apps of messages, reactions, and channel changes in near real time.

Tw

Twilio

Sends webhooks for incoming SMS / calls, requiring a synchronous response body (TwiML) that dictates how to handle the call — a request/response webhook variant.

Za

Zapier / IFTTT

Entire “no-code automation” businesses are built almost entirely on chaining webhooks between thousands of third-party services.

StripeShopifyGitHubwebhookwebhookwebhookAutomation Hubtransforms + routesSend Slack MessageUpdate SpreadsheetCreate CRM Record
Fig 5 · Multi-provider aggregation — an automation hub (e.g. Zapier / IFTTT) fans webhook events out to arbitrary destinations.
Event FiresDeliver toendpoint?SUCCESSMarked DeliveredDONEFAILRetry after 1 minRetry after 5 minRetry after 30 minRetry after several hrsDead Letter QueueGIVE UPOps Alert + Recon.
Fig 6 · Failure & recovery — exponential retries over hours, then a dead-letter and a human in the loop.
18
Frequently Asked Questions

The Questions That Come Up Every Integration Review

Short, opinionated answers to the webhook questions that come up most often in interviews, design reviews, and post-incident reviews.

Is a webhook the same as an API?

Not quite. An API is typically something you call when you want data (“pull”). A webhook is something the other system calls when it has data for you (“push”). Many webhook systems are paired with a small management API for registering the webhook URL itself.

What happens if my server is down when a webhook is sent?

Most providers retry automatically with increasing delays for a period (often 24–72 hours). If your server is still down after all retries, the event is typically lost from the webhook stream — which is why a reconciliation job matters for critical data.

Can I test webhooks without deploying to production?

Yes — most providers offer a way to send test events, and local tunneling tools (like ngrok) let your locally-running server receive real webhook calls during development.

Do webhooks guarantee exactly-once delivery?

No. Nearly all real-world webhook systems only guarantee “at-least-once” delivery. Your receiver must be idempotent to safely handle duplicates.

How is a webhook different from a message queue?

A webhook is a single HTTP call from one system to another, with no built-in ordering, replay, or consumer-group semantics. A message queue (like Kafka) provides much stronger guarantees but requires both sides to integrate with the broker directly, rather than just exposing a URL.

19
Summary & Key Takeaways

Notify Me When Something Happens

Webhook-based integration flips the traditional “ask and wait” model of software communication into a “notify me when something happens” model.

Instead of one system constantly polling another, the source system pushes an HTTP request to a receiver’s endpoint the instant an event occurs — cutting latency, cutting wasted traffic, and decoupling systems from each other’s internals.

Building a solid webhook integration means treating it like any other piece of production infrastructure: verify every payload’s authenticity, acknowledge quickly and process asynchronously, guard against duplicate and out-of-order delivery, monitor delivery health continuously, and keep a reconciliation safety net for anything business-critical.

Key takeaways

  • A webhook is an HTTP callback the source system fires the instant an event happens — the inverse of polling.
  • Always verify signatures with a constant-time comparison before trusting a payload.
  • Respond fast (2xx within seconds) and do heavy processing asynchronously in a background worker.
  • Design for at-least-once delivery: store event IDs and make processing idempotent.
  • Use retries with exponential backoff, and route repeated failures to a dead letter queue.
  • Pair webhooks with periodic reconciliation for anything financially or operationally critical.
  • At scale, put a queue between event detection and HTTP dispatch, and scale receivers horizontally behind a load balancer.
i
Summary in one sentence

A well-designed webhook integration is boring on a good day, informative on a bad one, and never the reason a duplicate charge or a missed shipment quietly slipped through the cracks.