SIGSHIP

Guide · 2 min read · Updated

Supabase row level security (RLS), explained simply

If your app uses Supabase, row level security is the single most important setting to get right. Here's what it is and how to check yours, without the jargon.

What it is

Your Supabase database comes with a public key that lives inside your website. That's normal: it's how your site talks to the database. Row level security (RLS) is the lock that decides what that public key is allowed to do, table by table and row by row.

Without RLS, the public key can read every row in the table. With RLS on and a good rule (a policy), each person only sees their own data.

Why AI-built apps often miss it

AI tools create tables quickly so your app works right away. Turning on RLS and writing policies is a separate step, and it's easy to skip when everything already seems to work.

How to turn it on

For each table, ask your AI tool, or run this in the Supabase SQL editor (replace orders with your table name):

alter table orders enable row level security;

create policy "Users read their own orders"
  on orders for select
  using (auth.uid() = user_id);

This turns on the lock, then lets a logged-in person read only the rows where user_id is their own ID. Add similar policies for adding, changing and deleting rows.

The open-door mistake

A policy that says using (true) lets everyone through, so RLS looks on but protects nothing. Why it matters.

How to check yours

Questions

Is the Supabase anon key a secret?

No, it is designed to be public. It is only safe when row level security is on for every table that holds private data. The service role key is the secret one.

Does RLS slow down my app?

For most apps, not noticeably. Simple policies like matching the user ID are fast, especially with an index on that column.

More guides

Check your app before your users do.

Free, open source, and nothing leaves your computer.

$ npx sigship