Grants for anon, authenticated and service_role
Three roles, four privileges. This is the grid the tool fills in.
The three roles
| Role | When the Data API uses it | Row level security |
|---|---|---|
anon | A visitor who is not signed in. | Applies |
authenticated | A signed-in user. | Applies |
service_role | Server-side code that uses the secret key. | Bypassed. Keep the key off the browser. |
What each access choice grants
| Choice | anon | authenticated | service_role | Policies written |
|---|---|---|---|---|
| Public read | SELECT | SELECT | SELECT, INSERT, UPDATE, DELETE | One: read every row |
| Owner only | none | SELECT, INSERT, UPDATE, DELETE | SELECT, INSERT, UPDATE, DELETE | Four: own rows only |
| Private | none | none | SELECT, INSERT, UPDATE, DELETE | None (RLS on, so nothing gets through) |
The statements
Supabase's own example grants read to visitors and full access to signed-in users and the server:
-- Read-only access for anonymous clients
grant select on table public.your_table to anon;
-- Full access for signed-in users; RLS still applies
grant select, insert, update, delete on table public.your_table to authenticated;
-- Full access for server-side code using the service role
grant select, insert, update, delete on table public.your_table to service_role;
A grant only opens the door. Enable row level security and add policies in the same migration, or a granted table is readable by anyone holding that role.
Old defaults, for comparison
On projects that still auto-expose, a new public table receives select, insert, update, delete, truncate, references, trigger and, on Postgres 17, maintain for all three roles.
Write the fix for your tables
One table is free. The whole schema with a rollback file is $9 one-time, free during launch.
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 service_role need a grant too?
Yes. The change revokes default privileges from service_role as well, and Supabase's example grants it explicitly. Bypassing row level security is separate from having a table privilege.
Should anon ever get insert?
Only when signed-out visitors are meant to write, such as a public contact form, and then with a policy that limits what they can insert. This tool does not write that shape.
Sources
- Supabase docs: Securing your API, read 2026-11-10
- Supabase docs: Row Level Security, read 2026-11-10
- Supabase docs: Postgres Roles, read 2026-11-10
- Supabase changelog: Breaking Change: Tables not exposed to Data and GraphQL API automatically (published 2026-04-28), read 2026-11-10
Related
- Replit app says "permission denied for table"The new table has no grants. Paste it below and copy a fix prompt made for Replit.
- Owner-only tableEach signed-in user sees and changes only their own rows.
- Supabase table not exposed to the Data APIA new table is invisible to the API until a role is granted access. Here is the grant.
- Is my Supabase project affected?Run one query. No rows means new tables get no grants.