stripe → supabase
Stripe webhook fires before Supabase row exists checkout session
The webhook isn't late — your client insert is. Treat checkout.session.completed as the source of truth, upsert the subscription row by Stripe id, and never require a prior client write for the webhook handler to succeed.
Why it happens
The browser creates a Checkout Session and may insert a "pending" row. Stripe's checkout.session.completed webhook often arrives before that insert commits — or the insert fails silently. If your webhook does select where user_id = ? and 404s, you drop a paid event. The seam is ordering across two writers (client + Stripe), not Stripe reliability.
Env-var matrix
Variable · which dashboard · publishable / secret / signing · differs per environment?