Your Supabase project ships with two keys, and using the wrong one is the most common way apps leak their entire database. Here is where each lives and which to use.
The 30-second answer
- Open your project in the Supabase dashboard.
- Go to Project Settings (the gear icon) → API.
- Under Project API keys you'll see two values:
anonpublic— safe for the browser. This is the one your frontend uses.service_rolesecret— full admin access, bypasses Row Level Security. Server-side only.
Which key goes where
| Where | Key | Env var |
|---|---|---|
| Browser / frontend | anon public |
NEXT_PUBLIC_SUPABASE_ANON_KEY, VITE_SUPABASE_ANON_KEY |
| Server / API routes / edge functions | service_role |
SUPABASE_SERVICE_ROLE_KEY (never prefixed PUBLIC) |
The anon key is designed to be public — it only grants what your Row Level Security policies allow. The service_role key is the opposite: it ignores RLS entirely. If it ever reaches the browser bundle, anyone can read and write every row in your database.
The rule that keeps you safe
Never give a browser-exposed variable name (NEXT_PUBLIC_*, VITE_*) the service_role value. If you're not sure whether a key is exposed, assume it is and treat the service_role key like a password.
Related
Building this app? Deploy it on Hostwares. Connect your repo and HW — our AI DevOps agent — handles the move: it detects your framework, provisions or wires your database, injects the env vars your app expects (DATABASE_URL, SUPABASE_URL, SUPABASE_ANON_KEY…), and sets up SSL. You review and go live.