scribase
Guide

Write your first row-level security policies

Row-level security moves access control into Postgres, so a user only ever sees rows they are allowed to read — enforced once, honored by REST, realtime, and SQL alike. This guide enables RLS on a table, writes a per-user policy, adds tenant isolation, and shows how Scribase lints policies for cost.

Published September 23, 20266 min read

1.Enable RLS on the table

Row-level security is off by default. Once enabled, a table denies all access until a policy grants it, which is the safe starting point.

sql
alter table todos enable row level security;

2.Let users read and write their own rows

A policy uses the authenticated user id from the JWT to scope rows. This one lets a signed-in user see and change only the todos they own.

sql
create policy "own todos"
  on todos
  for all
  using (user_id = auth.uid())
  with check (user_id = auth.uid());

3.Add tenant isolation for a SaaS schema

For multi-tenant apps, scope by an org claim carried in the JWT so a member of one organization can never read another organization’s rows.

sql
create policy "tenant isolation"
  on projects
  using (org_id = (auth.jwt() ->> 'org_id'));

4.Keep the policy fast

The common failure is not a wrong policy but a correct one that scans under load. Scribase lints policies for cost so you catch an expensive predicate before it reaches production; index the columns your policies filter on.

sql
create index on projects (org_id);
FAQ

Common questions

Does a policy apply to the REST API and realtime?

Yes. Because policies live in Postgres, the /rest data API, realtime subscriptions, and direct SQL all enforce the same rules — there is no second access layer to keep in sync.

How do I know a policy will stay fast?

Scribase lints policies for cost so you catch an expensive predicate early, and you index the columns your policies filter on so scoping does not turn into a scan.

Ready to try it?

Start a free project and follow this guide against a real backend, or move an existing project in with a dry run first.