Which role does each Supabase key use?
The key picks the Postgres role. The role needs the grant.
Key to role
| Key | User signed in? | Postgres role | Row level security |
|---|---|---|---|
Publishable, sb_publishable_... | No | anon | Applies |
Publishable, sb_publishable_... | Yes | authenticated | Applies |
Secret, sb_secret_... | Not applicable | service_role | Skipped |
| Legacy anon key (a long JWT) | No / Yes | anon / authenticated | Applies |
| Legacy service_role key (a long JWT) | Not applicable | service_role | Skipped |
From Supabase's API keys guide, which lists the legacy anon key as the earlier version of the publishable key and the legacy service_role key as the earlier version of secret keys, and says Supabase is deprecating the two legacy keys by the end of 2026.
What that means for "permission denied for table"
The error is about the role, not the key. Swapping a legacy key for a new one changes nothing, because both resolve to the same role. The same guide: A missing grant returns a permission error, including for service_role, whereas a policy that matches no rows returns an empty result.
| Your request uses | Grant the new table needs |
|---|---|
Publishable key, visitor not signed in: runs as anon | grant select on public.your_table to anon; and only for public data |
Publishable key, signed-in user: runs as authenticated | grant select, insert, update, delete on public.your_table to authenticated; plus owner policies |
Secret key on your server: runs as service_role | grant select, insert, update, delete on public.your_table to service_role; |
Pick the access shape per table in the tool below and it writes all three roles at once.
Write the fix for your tables
One table is free. The whole schema with a rollback file is $9 one-time.
Waiting for a paste.
Who can reach each table
Your tables show up here, one row each, with a choice of who can reach them.
Parsed in your browser. Your SQL is never uploaded, and no site or database is scanned.
Questions
Does a publishable key mean the user is anonymous?
No. Supabase's guide says the application authenticates with the publishable key while the user authenticates separately through Supabase Auth. A signed-in user's requests run as authenticated.
Is the key starting with eyJ wrong?
It is a legacy key. Supabase's guide says publishable and secret keys are short strings, not JWTs, and that instructions telling you to copy a long key beginning with eyJ were written for the legacy keys.
Sources
- Supabase docs: Understanding API keys, read 2026-11-10
- Supabase docs: Postgres Roles, read 2026-11-10
- Supabase docs: Securing your API, read 2026-11-10
Related
- Grants for anon, authenticated and service_roleThree roles, four privileges. This is the grid the tool fills in.
- service_role gets "permission denied for table"The secret key skips policies. It does not skip grants. Add one line.
- Which grant does each call need?Tick what your code does. Copy the smallest grant that makes it work.
- 42501, PGRST205, 42P01: which error is yours?Match the code in the response. See its HTTP status and whether a grant is the fix.