How to Know If a Webhook Is Being Delivered
Three layers of evidence, each proving something the previous one does not. Most people check only the first and draw the wrong conclusion.
There are three separate facts here and they are routinely confused. The sender's dashboard proves an event was sent. Your web server log proves it arrived. Your database proves it was processed. Any two can be true while the third is false.
Layer 1: did the sender send it?
Start at the provider, because if no event was created, nothing downstream matters.
Check that the event exists, that a delivery was attempted, and what response was recorded. Stripe lists this under the event destination, GitHub under Recent Deliveries on the webhook settings page, and Shopify in the Dev Dashboard monitoring view.
If the event exists and no attempt was made, the subscription is wrong: the endpoint is disabled, the event type is not subscribed, or you are looking at the wrong mode.
Layer 2: did it reach your server?
This is the layer people skip, and it is the one that separates a network or proxy problem from an application problem in about five seconds.
If the sender says it delivered and your access log has nothing, the request is being stopped before your application. A WAF rule, Cloudflare bot protection, a rate limiter or an IP allowlist are the usual suspects, and none of them log into your application.
If the access log shows 200 responses, delivery is genuinely working and your problem is entirely in layer 3.
Layer 3: was it actually processed?
The most common production shape is to verify the signature, enqueue the payload, and return 200. That 200 means received, not processed, and everything upstream will report success regardless of what happens next.
The fix is to record receipt explicitly, before any processing, and record completion separately.
With those two columns you can answer the question directly, which is worth more than any dashboard.
A growing stuck count means your worker is broken. A last_seen that stopped advancing means delivery stopped. One query, two distinct diagnoses.
Testing without waiting for a real event
A request bin service is useful for confirming a sender is configured correctly, but point it at a throwaway URL rather than swapping your production endpoint, or you will silently stop receiving real events while you test.
Ongoing, rather than when you are already worried
Three checks cover it. Alert when the gap since the last received event exceeds your longest normal quiet period. Alert when the stuck count crosses a threshold. Reconcile daily against the provider's API to catch events that never arrived at all.
The first two are what a heartbeat and a simple query give you, and SensaCat covers that shape of check. The third is more work and is the only one that catches a provider that quietly stopped sending. Background in webhook monitoring.