Why isn’t my Stripe webhook updating Supabase?
Usually because the webhook points to the wrong URL, fails its signature check, or is blocked by database rules when it writes. I find which one in your app and fix it as a $750 Quick Fix, deployed in 3 business days.
In live mode, Stripe retries a failed webhook for up to three days. Signature checks need the raw request body, so parsing it first makes every event fail.
The usual causes
- The endpoint is registered in test mode only, or still points to a preview URL.
- The signing secret in your environment is from a different endpoint or mode, so every event fails verification.
- The handler parses the body as JSON before verifying it. Stripe signs the raw body, so the check fails.
- The handler writes with the anon key, and row-level security blocks the write.
- The function times out or returns an error, and nothing logs it.
- The app listens for the wrong event, for example checkout.session.completed but not invoice.paid for renewals.
How a reliable setup looks
- One endpoint per environment, each with its own signing secret.
- Signature verified on the raw body before anything else.
- Writes done server-side with a key that never reaches the browser.
- Each event ID stored, so a retried event is not processed twice.
- A return value of 2xx only after the database write succeeds.
- A way to compare Stripe and your database, and fix any that disagree.
Where to look first
In the Stripe dashboard, open Developers, then Webhooks, and pick your endpoint. Failed deliveries show the status code and response. A 400 usually means a signature problem, a 401 or 403 an auth problem, and a 500 an error in your handler.