Skip to content

Row-Level Security (RLS)

Implement fine-grained access control at the row level for multi-tenant applications.

Enabling RLS

ALTER TABLE orders ENABLE ROW LEVEL SECURITY;

Creating Policies

Basic Tenant Isolation

CREATE POLICY tenant_isolation ON orders
FOR ALL
USING (tenant_id = current_tenant());

Read-Only Public Access

CREATE POLICY public_read ON products
FOR SELECT
TO PUBLIC
USING (published = true);

Insert Validation

CREATE POLICY insert_own_data ON documents
FOR INSERT
WITH CHECK (owner_id = current_user);

Policy Types

TypeDescription
PERMISSIVEMultiple policies are OR’d together
RESTRICTIVEMultiple policies are AND’d together

For All Operations

CREATE POLICY full_access ON accounts
FOR ALL
USING (owner_id = current_user)
WITH CHECK (owner_id = current_user);

System Functions

FunctionDescription
current_userConnected user: the PostgreSQL login, or the REST token’s sub
current_tenant()Current tenant ID, bound by \tenant use in the REPL; NULL when no tenant context is bound (PostgreSQL port, REST API), and a policy comparing against it then denies the row

Superusers, including the built-in postgres and helios accounts, bypass RLS: connect applications as non-superuser roles.

View Policies

SELECT * FROM pg_rls_policies();

REPL Commands

Terminal window
\tenant rls create orders policy_name "tenant_id = current_tenant()"
\tenant rls list orders
\tenant rls delete orders policy_name

Disabling RLS

ALTER TABLE orders DISABLE ROW LEVEL SECURITY;
DROP POLICY policy_name ON orders;