
Supabase Publishable Key vs Anon Key: What Actually Matters
What matters when choosing between Supabase publishable keys and anon keys for frontend apps.
Supabase key naming can be confusing, especially if you are reading older tutorials while using a newer Supabase project.
You may see:
- anon key
- publishable key
- service_role key
- secret key
If you are building a frontend app, the main question is usually:
Which key can safely be used in the browser?
The answer depends on the key type, but the security model is bigger than the key name.
The simple rule
For frontend code:
Use the public frontend key Supabase intends for client-side access.
For backend code:
Keep secret and service role keys server-only.
Do not put server secrets in browser code.
Why the naming causes confusion
Many older Supabase examples use the anon key in frontend code.
Newer projects may emphasize publishable keys.
This can lead developers to ask:
- Is the anon key deprecated?
- Is the publishable key safer?
- Can users see it?
- Does this replace RLS?
The key point is:
A frontend key is still public. It must be paired with proper RLS policies.
Changing the key name does not remove the need for authorization rules.
What a frontend key can do
A frontend Supabase key allows the browser client to talk to Supabase.
But the database should still enforce what that client can access.
That enforcement comes from:
- authentication state
- RLS policies
- storage policies
- allowed operations
- table design
The key opens the door to Supabase.
RLS decides which rooms the user can enter.
What should not be public
Never expose keys that can bypass user-level policies.
For example:
SUPABASE_SERVICE_ROLE_KEY=...This belongs on the server only.
In Next.js, avoid this mistake:
NEXT_PUBLIC_SUPABASE_SERVICE_ROLE_KEY=...The NEXT_PUBLIC_ prefix means it can be exposed to the browser.
That is not what you want for a secret.
A safe environment variable pattern
For frontend:
NEXT_PUBLIC_SUPABASE_URL=...
NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY=...For server-only usage:
SUPABASE_URL=...
SUPABASE_SERVICE_ROLE_KEY=...Then use the frontend key only in browser/client code.
Use the service role key only in trusted server code.
Do not use key changes to hide policy bugs
If you get this error:
new row violates row-level security policyThe fix is usually not to switch to a more powerful key.
The fix is to write the correct policy.
For example:
create policy "Users can insert their own rows"
on todos
for insert
to authenticated
with check (
auth.uid() = user_id
);That policy expresses the actual rule:
Users can create rows that belong to themselves.
That is better than bypassing RLS.
Practical decision tree
Ask:
1. Is this code running in the browser?
Use a public frontend key.
2. Is this code running on the server?
You may use a secret key if the operation truly needs it.
3. Is this normal user data access?
Use RLS.
4. Is this an admin operation?
Keep it server-only and narrow.
What I use as a safety check
Before shipping, I check:
- No
service_rolekey in frontend code - No secret key with
NEXT_PUBLIC_ - RLS enabled on user data tables
- Separate policies for select, insert, update, and delete
- Negative tests for cross-user access
- Storage policies reviewed separately
Most production issues come from skipping one of those.
A small guide I made
I built FixRLS to help developers generate Supabase key placement guidance and RLS starting points without connecting to their project or asking for secrets.
For publishable key guidance, start here:
https://fixrls.dev/supabase-publishable-key
Final thought
The publishable key vs anon key question matters, but it is not the whole security story.
The bigger rule is:
Public keys are expected to be visible. Secret keys are not. RLS is what protects user data.
Related FixRLS page
For this specific issue, use the matching FixRLS page: https://fixrls.dev/supabase-publishable-key
Author

Categories
More Posts

How I Fixed "new row violates row-level security policy" in Supabase
A practical mental model for fixing Supabase new row violates row-level security policy errors without bypassing RLS.


Is It Safe to Expose Your Supabase Anon Key?
How to reason about visible Supabase anon keys, RLS policies, and what actually protects user data.


Why You Should Never Put Your Supabase `service_role` Key in the Frontend
Why the Supabase service_role key must stay out of browser code and what to do if it leaked.

Newsletter
Join the community
Subscribe to our newsletter for the latest news and updates