We had a webhook endpoint that could jump to five times its normal traffic in less than a minute, overwhelming the origin and causing dropped events. We placed a small edge function in front of it that immediately acknowledges the request, forwards the payload asynchronously, and stores it in durable edge storage if forwarding fails. This now handles about 195 million requests per month for roughly $92, while the origin only receives successfully forwarded traffic. We have not observed dropped events, including tests with payloads up to 10 MB. One important implementation issue took a while to find: the request body cannot be read after sending the response. Small payloads appeared to work because they fit in the initial chunk, while larger real-world payloads failed in production. For similar webhook systems, where would you choose edge buffering versus putting the request directly into a durable queue and processing it with consumers?
3 Answers
The edge pattern is reasonable when you need to absorb sudden bursts close to the sender and the edge storage has clear durability and replay guarantees. Make sure the forward operation is idempotent, preserve enough metadata to retry safely, enforce payload and retention limits, and monitor the retry store and oldest queued event. Once you need sustained backlog management, ordering, consumer scaling, dead-letter handling, or stronger delivery guarantees, a managed queue with workers is generally the better boundary.
Returning an immediate 200 is only appropriate when the sender treats that as final acceptance and does not require the result of downstream processing. If the sender expects the response to reflect validation or business logic, acknowledge with a status such as 202 after durably recording the event, then process it asynchronously. Otherwise failures can be hidden from the caller.
If the webhook sender does not need the processing result, this can work, but a durable queue is usually a cleaner design. Accept the request only after successfully writing it to the queue, then let workers poll the queue and handle retries. Queue depth, dead-letter messages, and processing latency are straightforward to monitor, and the origin is removed from the synchronous path entirely.
That approach also makes the delivery contract clearer: acknowledge only after durable acceptance, rather than returning success before the event has actually been safely stored.

The biggest practical distinction is whether the edge layer is acting as a short-lived shock absorber or becoming the actual message broker. If it is the latter, using a queue directly usually reduces custom failure modes.