Row Level Security (RLS) is what stands between your users and each other's data in Supabase. These are three mistakes that show up again and again, with the fix for each.
1. RLS was never enabled
A table created with plain SQL has RLS switched off. Turn it on and add a policy:
alter table notes enable row level security;
create policy "owner can read" on notes
for select using (auth.uid() = user_id);2. Views skip RLS
A view runs with its owner's rights unless you create it with security_invoker = true (Postgres 15 and newer). Without it, a view can expose rows the current user should not see.
create view my_notes with (security_invoker = true) as
select * from notes;3. Trusting user_metadata in a policy
Users can edit their own user_metadata, so never use it to decide roles or permissions. Use app_metadata or a roles table that only your server can write to.
Free cheat sheet
Get these checks on one page: Supabase RLS Cheat Sheet (free PDF).
Want more patterns?
I put 31 copy-paste RLS patterns (ownership, teams, roles, sharing, invites, soft delete and testing) into one guide: Supabase RLS Policies: Copy-Paste Examples. If you are building on Next.js and Supabase, the Start here collection has the production checklist, the starter kit and the full bundle. All purchases come with a 14-day money-back guarantee.