Guides

Supabase RLS checklist for AI-built apps

A step-by-step Row Level Security checklist for Supabase apps generated by Lovable, Bolt, Cursor or v0.

1. Find tables with RLS off

In the SQL editor run: select tablename, rowsecurity from pg_tables where schemaname = 'public'; Every table holding user data should show true.

2. Enable RLS

alter table public.your_table enable row level security; Once enabled with no policies, the API returns no rows for that table. That is safe but will look like your data disappeared.

3. Add policies per operation

Write separate policies for select, insert, update and delete. For owner-only data use auth.uid() = user_id. A check of auth.uid() is not null only means signed in, which lets any user read every row.

4. Default the owner column

alter table public.your_table alter column user_id set default auth.uid(); so inserts pass the insert policy without the client sending user_id.

5. Keep the service role key off the client

The service role key bypasses RLS. It must only live in server code or Edge Functions, never in a VITE_ or NEXT_PUBLIC_ variable. If it was ever shipped to the browser, rotate it.

6. Test from two accounts

Sign in as user A, create data, then sign in as user B and try to read and edit it through the app and through the API. B should see nothing of A's.

7. Check views and functions

Views can bypass RLS depending on how they are created, and security definer functions run with the owner's rights. Review both after enabling RLS.

Sources

Have a specific error? Try the error explainer or the pre-launch checklist.