Supabase RLS best practices
Enabling RLS is only half the job. Permissive or incorrect policies leave data exposed even with RLS 'on'. These are the practices that make Supabase row-level security actually protect your data.
Step by step
- 1
Deny by default, allow explicitly
Enable RLS on every table so access is denied by default, then add narrow policies. Never use a 'true' / allow-all policy on tables with private data.
- 2
Scope policies to the user
Use auth.uid() to limit rows to their owner, e.g. USING (auth.uid() = user_id). Write separate policies per operation (select/insert/update/delete) and use WITH CHECK on writes.
- 3
Protect against privilege escalation
Keep the service-role key server-side only — it bypasses RLS. Don't expose views or SECURITY DEFINER functions that leak data around your policies.
- 4
Test as anonymous and as a user
Verify anonymous requests return nothing and that one user cannot read or write another user's rows. Re-run the free RLS checker to confirm.
Want it verified, not just fixed?
Fixing it is step one. A ClearedToShip review confirms the fix actually holds and gives you a signed, insured clearance to launch. Join early access: