Stripe webhook not firing? Here's how to catch it.
"Stripe webhook not firing" is one of the most common silent failures in indie SaaS. Stripe sends the event; your endpoint just doesn't process it — and nothing in your stack tells you.
Why Stripe webhooks fail silently
- A redeploy changes your route. Your webhook handler moves or gets renamed, and Stripe keeps posting to a 404 that nobody checks.
- Signature verification throws. A rotated `STRIPE_WEBHOOK_SECRET` that wasn't updated in production causes every event to be rejected with a 400 — Stripe retries a few times, then gives up.
- Your handler times out. A slow database call inside the handler causes Stripe to see a timeout, retry, and eventually mark the endpoint unhealthy.
- You only find out from a support ticket when a customer says they paid but didn't get access.
How to monitor for it
Uptime monitors won't catch this — your app is up, the webhook route can even return 200 for an unrelated reason. You need something that tracks whether the events you expect keep arriving. That's exactly what an event-based check does:
- Create a business-event check with a threshold like "at least 1 event every 6 hours".
- Add a second Stripe webhook endpoint pointed at the relay URL, alongside your real one.
- SilentWatch counts
invoice.paidandcheckout.session.completedevents by type. - If the count drops to zero inside your window, you get an email before a customer does.
Stripe Dashboard → Developers → Webhooks → Add endpoint
https://silentwatch.app/api/stripe-relay/sw_your_tokenA belt-and-suspenders setup
Keep your primary webhook endpoint exactly as it is. Add SilentWatch as a second, independent listener for the same events. If your primary handler breaks, the relay keeps receiving events (or stops receiving them, which is the actual signal), so you get alerted regardless of what broke on your side.