Supabase

Supabase RLS, explained like you're a founder — not a DBA

6 min read · VibeSafe Blog

Row-Level Security is the single most important switch in your Supabase project. Here's what it does, why AI tools keep leaving it off, and how to set it up in plain English.

The mental model

Your Supabase database is a filing cabinet in a public hallway. The anon key that ships in your frontend is a hallway pass — everyone who visits your app has one. RLS policies are the locks on each drawer. Without them, the hallway pass opens everything: every user's rows, every table, read and often write.

Why AI tools leave it off

An app with RLS enabled and no policies written returns no data at all — which looks broken in a demo. So generated code often works around it: RLS disabled, filtering done in the frontend with .eq('user_id', ...). That filter is a suggestion, not a rule — anyone can remove it and query the whole table.

The two-step fix

Step 1: enable RLS on every table (Supabase dashboard → table → RLS toggle, or ALTER TABLE x ENABLE ROW LEVEL SECURITY;).

Step 2: write a policy per table that scopes rows to the logged-in user:

CREATE POLICY "own rows" ON todos FOR ALL USING (auth.uid() = user_id);

That one line means: this drawer only opens for the person whose name is on the folder.

The three mistakes to avoid

A scan with VibeSafe flags the code-side patterns (service_role in frontend, client-side-only filtering) — and always confirm the RLS toggles directly in your Supabase dashboard.

Scan your Supabase app free →

3 free scans every month · Your code is never stored

An honest note. VibeSafe helps catch the most common risks in AI-built apps quickly. It doesn't replace a professional security audit for high-risk applications.

Related: