Auth, RLS and the service-role key are where most Supabase apps break in production.
What we check
- NEXT_PUBLIC_SUPABASE_URL and NEXT_PUBLIC_SUPABASE_ANON_KEY are present and match the project ref.
- SUPABASE_SERVICE_ROLE_KEY is referenced only in server code paths, never under NEXT_PUBLIC_.
- Tables enabled for the Data API have RLS turned on and at least one policy per CRUD action used by the app.
- Auth redirect URLs include every preview, production and custom domain.
- GRANT statements exist for every public table — RLS without grants returns a permission error from PostgREST.
How to fix
- Move service-role usage behind a server function or route handler and rotate the key if it was ever bundled.
- Add `auth.uid() = user_id` policies for SELECT/INSERT/UPDATE/DELETE on every user-scoped table.
- Register every preview domain (e.g. *.vercel.app) in Authentication → URL Configuration.
Run a diagnosis Most Stripe outages in deploys are signature mismatches, wrong endpoint mode, or the wrong webhook secret per environment.
What we check
- STRIPE_WEBHOOK_SECRET is set per environment — the test endpoint and live endpoint have different secrets.
- The handler verifies the signature using the raw request body, not the parsed JSON.
- STRIPE_SECRET_KEY mode (sk_test vs sk_live) matches the dashboard mode the endpoint was created under.
- Endpoint URL is reachable from Stripe (no auth wall in front of /api/webhooks/stripe).
- Selected events include checkout.session.completed and invoice.payment_succeeded if you fulfill on payment.
How to fix
- Use Stripe CLI `stripe listen --forward-to /api/webhooks/stripe` locally and copy the new secret into .env.local.
- In Next.js App Router, read `await req.text()` before constructing the event — `req.json()` will break signature verification.
- Put `/api/webhooks/*` on the public-route whitelist in your auth middleware.
Unlock on ProAI provider failures in production are almost always missing keys, wrong project scope, or rate-limit blowups without backoff.
What we check
- OPENAI_API_KEY / ANTHROPIC_API_KEY are present in production and never bundled with NEXT_PUBLIC_.
- Keys are scoped to the right project / workspace — sk- vs sk-proj- vs sk-ant- prefixes match the dashboard you generated them from.
- Calls happen from server functions, not from React components or loaders that run on the client.
- 429 / overloaded responses are retried with exponential backoff and jitter.
- Streaming responses set the correct Content-Type and never sit behind a buffering proxy.
How to fix
- Move every provider call into createServerFn or a /api route — replace `import OpenAI` from client components.
- Wrap calls in a small retry helper (max 3 attempts, 250ms → 1s → 3s) and surface a typed error to the UI.
- Add a server-only env loader so missing keys fail fast at boot instead of mid-request.
Unlock on ProAuth providers usually fail in production because of mismatched URLs, JWT template drift, or middleware that runs in the wrong runtime.
What we check
- Clerk: NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY and CLERK_SECRET_KEY belong to the same instance and same environment (development vs production).
- Auth0: AUTH0_BASE_URL, AUTH0_ISSUER_BASE_URL and AUTH0_SECRET are set; allowed callback URLs include preview + prod.
- Edge middleware does not import Node-only libraries — both providers ship edge-compatible helpers.
- JWT templates / API audiences used by the backend match the ones the frontend requests.
- Logout URLs and post-login redirects are whitelisted for every deployed domain.
How to fix
- Generate per-environment keys in the provider dashboard and store them in the matching Vercel/Netlify environment.
- Move `clerkMiddleware()` / `withAuth()` into middleware.ts at the project root — putting it inside a route file silently disables it for other routes.
- Add every deploy URL (preview, prod, custom domain) to allowed callback + logout URLs in one go.
Unlock on Pro