Full practical guide on creating production-grade webhook receivers
Throughout my career I have designed and implement tens of webhook handlers from Payments systems and delivery trackers to chat and real time communication backends and crypto services. Although all software providers use different rules, authentication mechanisms, and retry policies, the same fundamental knowledge applies to all cases. In this tutorial I will share my experience on how to…
Designing, implementing, testing, and deploying production-grade webhook handlers is crucial for various systems, including payments, delivery trackers, chat platforms, crypto services, and more. This tutorial aims to share experiences and guidelines on building secure and reliable webhook handlers. The full tutorial can be found in the webhook-consumer-handbook repository.
A webhook is an event or process in which one server sends a notification to another server, allowing for communication about specific events. For instance, when someone makes an order through an e-commerce system, a webhook can be used to store the order information in your database, send an email notification to the user, and confirm order confirmation.
A typical webhook receiver flow involves receiving a request, authenticating the request, validating the payload, and executing the consumer in a recoverable manner. To receive a request, a POST endpoint must be added to your server with a reasonable internal name for the endpoint URL. Store this URL in environment variables to easily update the webhook without redeploying the app.
To authenticate the request, consider using authentication methods such as HMAC signature verification, bearer token, or basic authentication. Additionally, some providers publish fixed IP addresses, allowing you to inspect the source IP address and allow or reject the request based on that list. Always store tokens, passwords, and keys in specialized secret managers like AWS Secrets Manager.
When validating the payload, treat it as untrusted input and parse it into explicit validator classes or DTO objects before running business logic. This ensures that the application works with a known and predictable data shape. If payload validation fails, return a client error such as 400 Bad Request and log the error.
Webhook providers may deliver the same event multiple times due to retries, network issues, or provider-side wrong delivery. To handle this, use an idempotency key to detect whether the same event has already been accepted or processed. Build the key from the event identity, store processed keys, discard duplicates, and return a successful status for duplicates. This prevents the provider from continuously retrying deliveries due to non-2xx status codes.
Ensure consistent state by storing event details and timestamps when available. Before updating records, check whether the incoming event represents a newer state. Avoid moving completed payments back to pending status due to delayed webhook deliveries. Define valid state transitions in the application and log unexpected provider events.
Written by urgent.news from Dev.to's reporting — not their text. Machine-written — may contain errors; check the original before relying on it.