What is a webhook and when should you use one
You have two systems that need to talk to each other. System A has data that System B cares about. How does System B find out when something changes?
The obvious answer is polling: System B asks System A "anything new?" every few seconds. This works, but it is wasteful. Most of the time, the answer is "no, nothing new," and you have burned an API call for nothing. If you poll too frequently, you waste resources. If you poll too infrequently, you miss time-sensitive updates.
Webhooks flip this model around. Instead of System B constantly asking System A for updates, System A pushes updates to System B the moment something happens. System B provides a URL (the webhook endpoint), and System A sends an HTTP POST request to that URL whenever there is new data.
How webhooks work in practice
When you integrate with a service that supports webhooks, you typically register an endpoint URL with that service. This is your callback URL, the place where you want to receive notifications. When an event occurs (a payment succeeds, a user signs up, a file is uploaded), the service constructs an HTTP request containing information about that event and sends it to your endpoint.
Your server receives this request like any other incoming HTTP request. You parse the payload, validate that it actually came from the expected sender, and then do whatever your application needs to do with that information. Finally, you return a 200 OK response to acknowledge receipt.
The service on the other end typically expects a quick response. If your endpoint takes too long to respond, or returns an error status code, the sender may retry the webhook. Most webhook providers implement retry logic with exponential backoff, attempting delivery several times before giving up.
The anatomy of a webhook request
A webhook request is just an HTTP POST with a JSON body, though some services use other formats. The request usually includes several important pieces of information.
The payload contains the actual event data. This might be the full details of the object that changed, or it might be a minimal notification that something happened (requiring you to fetch details separately). The choice between "fat" and "thin" payloads is a design decision with tradeoffs we will cover in a later article.
Headers often carry metadata like the event type, a signature for verification, and a timestamp. The signature is critical for security since it lets you confirm the request actually came from the expected sender and was not spoofed by an attacker.
An event ID or delivery ID helps you handle the same webhook being delivered multiple times. Network issues and retry logic mean you might receive the same event twice, and you need to make sure you do not process it twice.
When webhooks are the right choice
Webhooks excel when you need to react to events in near real-time but do not need to maintain a persistent connection. They are ideal for integrating with third-party services where you want to know immediately when something happens but you do not control the other system.
Common use cases include payment notifications (Stripe telling you a charge succeeded), version control events (GitHub notifying you of a push), communication triggers (Twilio alerting you to an incoming SMS), and e-commerce updates (Shopify informing you of a new order).
Webhooks also make sense when events are relatively infrequent. If you are dealing with thousands of events per second, you might want to consider a message queue or streaming solution instead. But for the typical case of occasional events that need prompt handling, webhooks are simple and effective.
When webhooks are not the right choice
Webhooks require your server to be reachable from the internet. If you are behind a firewall without a public endpoint, receiving webhooks becomes complicated (though tools like ngrok can help during development).
If you need guaranteed ordering of events, webhooks can be tricky. Network conditions may cause events to arrive out of order, and you need to handle this in your application logic.
For high-frequency, bidirectional communication, WebSockets or Server-Sent Events are better choices. Webhooks are fundamentally a push-and-forget mechanism. Each request is independent, with no persistent connection between sender and receiver.
Finally, if the sender does not support webhooks, you are back to polling. Not every API offers webhook functionality, though it has become increasingly common.
Getting started
To receive webhooks, you need three things: an HTTP endpoint that can accept POST requests, logic to parse and validate incoming payloads, and a way to acknowledge receipt with an appropriate status code.
In the following articles, we will build webhook receivers from scratch, compare webhooks to alternative approaches in depth, and dive into the security considerations that every webhook implementation needs to address.