Webhooks are fun to think about. A couple more issues off the top of my head:<p>* Ordering. Since network requests can take variable amounts of time, how do you ensure those two "foo.updated" events are processed in order, or that the receiver can tell their order? Especially something to consider if the webhooks will retry a few times on intermittent failures.<p>* Consistency. Always a concern in distributed microservice land, but maybe more acute when generating webhooks right as things are updated: if the receiver uses the webhook to make an API request right back into the system, will the API have the same view of the data?<p>* DDoS. How do you make sure the webhook destination URL is owned by the subscriber? If your system can generate high volumes of webhook traffic, that could be a problem.<p>* Infinite loops. A silly one, but the user could conceivably point the webhook at a URL of the system that sends the webhook, in such a way that it will cause a new webhookable event to be generated.
Some interesting previous discussions here:<p>- Best Practices for Using Webhooks (stripe.com): <a href="https://news.ycombinator.com/item?id=32521159">https://news.ycombinator.com/item?id=32521159</a><p>- Collection of best practices for providing and consuming webhooks (webhooks.fyi): <a href="https://news.ycombinator.com/item?id=32517645">https://news.ycombinator.com/item?id=32517645</a><p>- Give me /events, not webhooks (sequin.io): <a href="https://news.ycombinator.com/item?id=27823109">https://news.ycombinator.com/item?id=27823109</a>
For a server sending webhooks to endpoints entered in by users, take care that:<p>a: The FQDN does not resolve to an RFC1918 address (You don't want to be POSTing payloads to endpoints within your internal network.)<p>b: If you respond to redirect responses (easier to just not do so for other reasons as well) also make sure those don't resolve to internal addresses too!
Those terms are very confusing - to me orign would be the SENDER ... where the message ORIGNates from ...<p>But yes, those are common scenarios, and most services that offer calling a webhook have retries baked in for such things. It is the responsibility of the consumer to verify if they have already received a message or not.<p>You should not be consuming a webhook 'live' and attempting to work on it the moment you receive it - that way lies dragons!<p>I have dedicated endpoints for services to send to, and they are verified and consumed as quickly as possible and put into a queue to be processed after. That way I can at least see what was sent, and if we missed something.
There are so many more failure scenarios!<p>I wrote a post about common TLS errors recently: <a href="https://www.svix.com/blog/ssl-tls-incomplete-certificate-chain/">https://www.svix.com/blog/ssl-tls-incomplete-certificate-cha...</a>
That needs better naming in my opinion.<p>Just sender and receiver would be enough IMO.<p>Maybe it is just me but it is unusual to see origin used in this context even if it is technically correct I only ever see it used with CDNs and load balancing.
At the most basic level, what I like to do is create a webhook response controller, the controller enqueues a job and immediately returns an HTTP 200.<p>The job is saved in my postgres database, using Oban (Elixir) so I have observability, accurate bug stacktraces are saved in the job record's error field, and I can see how many times the job has been attempted.
Very cool article.<p>I'm one of the creators of <a href="https://webhooks.fyi/" rel="nofollow noreferrer">https://webhooks.fyi/</a> and will do a PR to add this one. Thanks!
The way I solve all these problems is.<p>Prerequisite: require receiver to be able to process duplicate webhook being resent.<p>Algorithm outline:<p>1. Have webhook body stored by sender<p>2. Attempt to send body to receiver<p>3. If 2x status returned mark webhook as sent. Done<p>4. Otherwise for any other status or timeout increment attempt for webhook and try again later until maximum attempts (which then mark webhook as failed)<p>This covers the tricky case where success response gets dropped in network by having the sender time out and retry later. The receiver gets a duplicate
Any suggestions to alternative to webhooks? I feel a ‘pull’ based model with cursors and long polling would be simpler and more reliable than webhooks.
right out of the gate: why not use the terms "sender" and "receiver" instead of "client" and "origin"?<p>the author uses "client" to refer to the application <i>sending</i> the webhook, and "origin" to refer to the application <i>receiving</i> the webhook. this is all backwards to me.<p>I often say that naming things is hard, but it isn't so hard that this needs be the result.