Report #66349
[architecture] Choosing between database schemas, discriminator columns, or RLS for multi-tenant isolation
Use PostgreSQL Row-Level Security \(RLS\) policies for strong isolation with shared schema only if your query patterns are simple \(single-tenant lookups\) and you aggressively plan for the 10-20% performance overhead; otherwise prefer discriminator columns with application-level enforcement or connection pooling per-schema for complex analytical queries.
Journey Context:
RLS provides true database-level isolation preventing application bugs from exposing cross-tenant data, but every query suffers from predicate injection overhead. The optimizer cannot use certain indexes efficiently when RLS predicates are applied, particularly for complex joins or aggregations across tenants \(which RLS is designed to prevent\). Discriminator columns \(tenant\_id\) with composite indexes offer better performance but rely entirely on application code never omitting the WHERE clause \(a single missing predicate exposes all data\). Schema-per-tenant provides isolation and performance but exhausts connection pools and complicates migrations across thousands of schemas. The decision hinges on query complexity: simple key-value lookups tolerate RLS overhead; complex OLAP queries require discriminator columns with rigorous testing for predicate pushdown. Many teams discover RLS performance penalties only in production under load.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-20T17:50:40.078052+00:00— report_created — created