Guide Supabase
What is Supabase's October 30 grants change, and will it break my app?
Short answer
On October 30, 2026, Supabase applies a new default to all existing projects: tables you create in the public schema after that date are no longer reachable through the Data API (supabase-js, REST and GraphQL) until you grant them to a role. Tables that already exist keep their current grants and keep working. If an app built with Lovable, Bolt, Replit or Cursor creates a new table after the change without a GRANT, requests to it fail with error 42501, "permission denied for table". The fix is to grant only the roles that need the table, keep Row Level Security (RLS) on, and add policies in the same migration. Don't turn RLS off and don't run GRANT ALL ... TO anon.
What is the timeline?
- April 28, 2026: new projects could opt in at creation (the "Automatically expose new tables" checkbox unchecked).
- May 30, 2026: the new behavior became the default for new projects, rolled out gradually.
- October 30, 2026: Supabase applies it to all existing projects.
Supabase's changelog says: "Existing tables are not affected in your project, they keep their current grants and stay reachable." If your app talks to Postgres only over a direct connection (psql, an ORM or a server with a connection string), the change does not affect you.
What exactly changes?
Until now, a Supabase project granted select, insert, update and delete on every new public table to the anon, authenticated and service_role roles, so every table was reachable through the API the moment it was created. After the change, a new table gets no Data API grants until you add them.
Grants and RLS are two separate layers. Grants decide whether a role can reach a table at all. RLS decides which rows it can see. If the grant is missing, Postgres rejects the query before RLS is even checked.
What does the error look like?
PostgREST returns code 42501 with a hint naming the missing grant:
{
"code": "42501",
"message": "permission denied for table your_table",
"hint": "Grant the required privileges to the current role with: GRANT SELECT ON public.your_table TO anon;"
}
Treat the hint as a clue, not a command. It names anon because the request came from a signed-out visitor. If the table holds private data, the right fix is usually to grant authenticated and require sign-in, not to open the table to everyone. Full walkthrough: Supabase error 42501: the safe fix.
How do I fix a new table safely?
Ship the grant, RLS and the policies together in one migration. Example for a private notes table with a user_id column:
begin;
alter table public.notes enable row level security;
grant select, insert, update, delete on table public.notes to authenticated;
create policy "notes_own_rows" on public.notes
for all to authenticated
using ((select auth.uid()) = user_id)
with check ((select auth.uid()) = user_id);
commit;
For data that really is public (a menu, blog posts), grant select to anon and add a read-only policy. Grant service_role only if server-side code needs the table.
What should I tell Lovable, Bolt, Replit or Cursor?
AI tools that create tables in migrations may not add grants yet. Paste something like this into the project chat:
Whenever you create a table in the public schema, add in the same migration: enable row level security, the minimum GRANT each role needs (authenticated for private data, anon only for public read-only data), and policies so each user reaches only their own rows. Never disable RLS and never grant ALL to anon.
Then check the result in your project's Security Advisor (on Bolt Cloud, the database Security tab runs the same checks).
How do I check which tables are exposed now?
This read-only query in the Supabase SQL editor lists each public table, whether RLS is on, and whether the API roles can read it:
select c.relname as table_name,
c.relrowsecurity as rls_on,
has_table_privilege('anon', c.oid, 'select') as anon_select,
has_table_privilege('authenticated', c.oid, 'select') as auth_select
from pg_class c join pg_namespace n on n.oid = c.relnamespace
where n.nspname = 'public' and c.relkind in ('r','p')
order by rls_on, table_name;
Any row with rls_on = false and anon_select = true is readable by anyone with your project URL and public key. Fix those first; that risk exists today, Oct 30 or not.
Where we can help
Free instant check: paste your URL at patchandship.com/check.html to scan your homepage's JavaScript for secret keys and security headers (no signup, nothing stored). Paid, fixed price per app: Database Check, $49; Security Fix, $149 (every critical issue on our checklist fixed within 48 hours of working access); Fix & Deploy, $249. Otherwise a full refund if you ask within 14 days of purchase (Refund Policy). AI agents run the checks and a human engineer approves every change. Not a penetration test or a security guarantee.
FAQ
Will my existing Lovable or Bolt app break on October 30?
Not because of existing tables: they keep their grants. It can break when the app (or your AI tool) creates a new table afterward without a GRANT. That request then fails with 42501.
Is turning off RLS a valid fix for the 42501 error?
No. RLS off means any role with a grant can read and change every row. The error is about a missing grant, so add the grant for the right role and keep RLS on.
Should I run GRANT ALL ON my_table TO anon?
Almost never. It lets signed-out visitors reach the table and, with a loose policy or RLS off, read or change private data. Grant only the privileges and roles the app needs.
Does this change make my app more secure?
It makes new tables private by default, which prevents accidental exposure. It does nothing for tables you already have, so still check RLS on those.
Can I keep the old behavior?
Supabase's Data API settings have an "Automatically expose new tables" option. Re-enabling it brings back automatic grants, which is the riskier default. Explicit grants in migrations are safer.