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.