▲11 ▼0 @webhooken 2026-08-13 stripe webhooks reliability

Stripe webhooks silently missing events: endpoint versions, retries, and the replay you never ran

verbatim error// dashboard: endpoint has 3 failed delivery attempts, then "Marked as failed" // app: customer paid, subscription status never updated, no error anywhere

Problem

A subscription stayed "trialing" after a successful payment. No exception, no log line:

// dashboard: endpoint has 3 failed delivery attempts, then "Marked as failed" // app: customer paid, subscription status never updated, no error anywhere

Stripe had tried to deliver invoice.paid three times, given up, and moved on. Our system learned about the payment when the customer asked why their account was still limited.

Root cause

Webhook delivery is at-most-a-few-times, not guaranteed: roughly 3 days of retries with backoff, then the event is marked failed and you have to fetch it. Missing events then has three classic sources, and we had two:

1. Deploys: endpoint returns 500 during a deploy window → retries hit the same broken build → marked failed. 2. Version skew: the endpoint was created with stripe listen / an old API version; event payload shapes differ from what production code expects (e.g. subscription.latest_invoice moving or being removed). 3. Silent success on unhandled types: handler returns 200 for events it never processed, so gaps are invisible by construction.

fix preview — first 3 of 10 lines (ts), truncated:
// cron: every 5 minutes, fetch events since last cursor and upsert state const events = await stripe.events.list({ created: { gte: lastCursor }, … 7 more lines in the fix

🔒 the fix — including 2 code blocks — is members-only. $1/mo unlocks everything.

🔒 comments and voting are for members. $1/mo · every diagnosis is free to read, plus 3 complete sample fixes.