RLS

What is RLS?

Row Level Security

Row Level Security (RLS) is a Postgres feature, used by Supabase, that enforces access control at the row level. When RLS is enabled on a table, you write policies that say which rows each user can see, insert, update, or delete. Without RLS, any client with your Supabase anon key can read every row in every public table.

In more detail

Supabase exposes your database over HTTP using a public anon key. That key is meant to be public and ship with your frontend code. The only thing separating that key from full database access is RLS — turn it off on a table and the anon key can read and modify every row.

Policies are written in SQL and can reference `auth.uid()` (the current user's ID from the JWT) to compare against columns like `user_id` or `owner_id`.

Basic RLS policy for user-owned rows
-- Enable RLS
alter table public.posts enable row level security;

-- Users can read their own posts
create policy "users read own posts"
  on public.posts for select
  using (auth.uid() = user_id);

Why this matters

Why builders care

Supabase RLS-disabled tables are the single most common critical finding in AI-built apps. Lovable, Bolt, and Cursor sometimes scaffold Supabase without policies. Every table that ships to production must have RLS on, or the anon key is equivalent to admin access.

FAQ

Frequently asked questions

Can I disable RLS if I only query through my own backend?
Yes — if you exclusively use the service role key and never expose the anon key. But most AI-built apps use the anon key directly in the client, so RLS is required.
How do I make a table readable by everyone?
Enable RLS, then add a permissive policy: `create policy "public read" on public.posts for select using (true);`. Without insert/update/delete policies, those actions are still blocked.

See where your site stands

Paste a URL, get a score in 60 seconds. Free, no signup.