Next.js + Supabase security hardening for production
The default Supabase + Next.js setup is not production-ready. RLS gaps, exposed keys, missing headers, and auth misconfigurations explained and fixed.
The Supabase + Next.js combination is the most popular stack for indie SaaS. The default setup gets you running quickly, but it ships with assumptions that are dangerous in production: the anon key is public by design, RLS must be manually configured per table, and the service-role key has god-mode access to your entire database. If you do not harden these defaults, your production database is one leaked environment variable away from full exposure.
The anon key is public — that is intentional
The Supabase anon key is designed to be public. It lives in the browser and is gated by RLS. This is only safe if your RLS policies are correct and comprehensive. If a single table has RLS disabled, the anon key provides unrestricted read/write access to that table from any browser. Audit every table, not just the ones you think users interact with.
Service-role key isolation
The service-role key bypasses all RLS. It must never appear in client-side code, environment variables prefixed with NEXT_PUBLIC_, or published source maps. Use it only in server-side code: API routes, server actions, and middleware. If you are unsure whether it is exposed, PreFlight scans your production origin for it.
Security headers in next.config
Configure Content-Security-Policy, X-Frame-Options, X-Content-Type-Options, Referrer-Policy, and Permissions-Policy in your Next.js config. These headers prevent clickjacking, MIME sniffing, and unauthorized framing. Without them, your application is vulnerable to attacks that do not require finding a code bug.
Auth middleware that actually protects
Next.js middleware runs before every request. Use it to verify session tokens and redirect unauthenticated users away from protected routes. But middleware alone is not enough — your API routes must independently verify authentication. Do not rely on the middleware having already checked; a direct API call bypasses page-level middleware.
Continuous security verification
Security hardening is not a one-time task. Every dependency update, new feature, or configuration change can introduce regressions. PreFlight checks your security posture on every run: key exposure, RLS behavior, header configuration, and provider connectivity. This catches regressions before they reach production traffic.
