PostgreSQL RLS for multi-tenant SaaS security
Secure tenant data with PostgreSQL row-level security, restricted roles, transaction-scoped tenant context, safe policies and isolation tests.
In this guide
What is PostgreSQL row-level security for SaaS?
PostgreSQL row-level security (RLS) applies policies to the rows a database role may read or change. A multi-tenant SaaS can use it as a database-side guardrail so a missed tenant filter in an ordinary query does not automatically expose every customer's rows. RLS supplements application authorization and table privileges; it does not replace either one. When RLS is enabled and no applicable policy allows a row, PostgreSQL uses default deny for normal row access.
Put a stable tenant key on every tenant-owned row
Choose an immutable tenant identifier and carry it through parent and child records, files, jobs and audit events. Make the key non-null where every row must belong to a tenant, and add foreign keys or other integrity rules so a child record cannot silently point to another customer's parent. Identify global reference data that is intentionally shared.
Write policies for each operation the application performs
A SELECT policy controls visible rows, while INSERT, UPDATE and DELETE need policies that cover the relevant write paths. PostgreSQL supports USING and WITH CHECK expressions for different parts of those decisions. Test create, read, update, delete, upsert, bulk operations and background jobs instead of assuming one policy handles every command correctly.
Treat a missing tenant context as a denied request
Set the active tenant from a server-validated session or job record after authorization. Never accept an arbitrary tenant identifier supplied only by a URL, form or SQL parameter. Define what the policy does when context is absent or malformed and verify it returns no tenant rows rather than falling back to a shared or default tenant.
| Table or data path | Tenant key and integrity rule | Allowed database role | Read/write policy tests | Owner and review date |
|---|---|---|---|---|
| Customer records | ||||
| Child records and attachments | ||||
| Background job data |
How should a SaaS team configure PostgreSQL RLS safely?
Run application queries as a restricted role, not the table owner
PostgreSQL table owners normally bypass RLS, as do superusers and roles with BYPASSRLS. Use a separate migration owner and a limited application role that cannot change policies or assume a privileged role. Consider FORCE ROW LEVEL SECURITY for owner behavior where appropriate, while remembering it does not constrain superusers or BYPASSRLS roles.
Set tenant context inside the same database transaction
For connection-pooled applications, assign context with a transaction-local setting or an equivalent verified mechanism, then run the tenant queries before the transaction ends. Session state can survive when a pooled connection is reused. Test rollback, exception, retry and connection reuse paths so the next request cannot inherit the previous tenant's context.
Keep application authorization and database grants explicit
RLS is evaluated only after ordinary SQL privileges permit an operation. Grant the application role access only to the tables and columns it needs, keep administrative and reporting roles separate, and review SECURITY DEFINER functions carefully. A privileged helper, view or connection path can reintroduce cross-tenant access if its behavior is not designed and tested deliberately.
How do you test and operate tenant row policies?
Test with two tenants and the real production application role
Create fixtures for tenants A and B, then verify that a caller authorized for A cannot read or alter B's rows through every supported route. Run tests as the same role used by the application, because a database owner or superuser test can bypass the policy and create false confidence. Include negative tests for missing context.
Review integrity side channels and non-row operations
PostgreSQL documents that referential-integrity checks bypass row-security filtering to preserve database integrity. Unique constraints, foreign keys, TRUNCATE, REFERENCES, exports and administrative queries therefore need separate review. Avoid error messages that reveal another tenant's identifiers or whether a protected row exists.
Make migrations, backups and support work tenant-aware
Use privileged paths only for a documented purpose and restrict who can invoke them. Confirm backups and restore jobs include all intended tenant data; PostgreSQL offers a row_security setting that can make a backup fail if policy filtering would omit rows. Test restore and migration scripts against isolated environments and record any controlled RLS bypass.
PostgreSQL RLS for SaaS FAQs
Does row-level security replace application authorization?
No. The application must still authenticate the user, decide which tenant they may act for and authorize the requested action. RLS adds a database boundary that can limit accidental row exposure when a query omits a tenant condition.
Is enabling RLS on one table enough to isolate a tenant?
No. Map every tenant-owned table and indirect data path, then check policies, grants, views, functions, exports, jobs and shared storage. A table without RLS or a privileged code path can defeat an otherwise correct policy design.
Can the PostgreSQL table owner bypass RLS?
Normally, yes. Superusers and roles with BYPASSRLS also bypass policies. Use restricted runtime roles and verify the effective role in tests; FORCE ROW LEVEL SECURITY changes ordinary table-owner behavior but does not remove superuser or BYPASSRLS privileges.
What is the safest source for the tenant ID in a query?
A server-side identity and authorization decision. Derive the tenant from a verified session or trusted job payload, set it for the active transaction, and test that missing or forged tenant context fails closed.
Related practical guides
Related issue guides
Sources and publication record
Draft prepared 27 September 2026; engineering, security and editorial review pending · Sources checked .
- Row Security PoliciesPostgreSQL Documentation
- AWS SaaS Lens: Preventing cross-tenant accessAmazon Web Services
- AWS SaaS Lens: Testing multi-tenant SaaS reliabilityAmazon Web Services
- OWASP Cheat Sheet: AuthorizationOWASP Foundation