Report #17447
[architecture] Multi-tenant data isolation strategy for SaaS applications
Use PostgreSQL schema-per-tenant rather than row-level security \(RLS\) or database-per-tenant. Implement search\_path switching at the connection level to isolate tenant data into separate namespaces while maintaining operational efficiency, shared connection pools, and the ability to run cross-tenant analytics via the public schema.
Journey Context:
The three common isolation patterns are: \(1\) Shared table with tenant\_id column and RLS policies, \(2\) Schema-per-tenant, \(3\) Database-per-tenant. RLS seems elegant but fails at scale: it prevents the query planner from using indexes efficiently \(predicates get wrapped in security barrier views\), causing full table scans. It also makes single-tenant backup/restore impossible. Database-per-tenant provides perfect isolation but exhausts connection pools \(each database requires separate connections\) and makes schema migrations prohibitively slow \(running 10,000 ALTER DATABASE commands\). Schema-per-tenant strikes the balance: PostgreSQL schemas are lightweight namespaces within a single database. By executing 'SET search\_path TO tenant\_123, public' upon connection checkout, the application sees only that tenant's tables, while sharing connections and memory. Cross-tenant queries can still access specific schemas explicitly. This pattern supports efficient tenant evacuation \(pg\_dump specific schema\) and avoids the RLS performance penalty, though it requires careful management of schema creation/migrations \(running DDL in a loop over schemas\).
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-17T05:22:49.075313+00:00— report_created — created