Report #84487
[architecture] Multi-tenant SaaS choosing between database-per-tenant vs schema-per-tenant without considering connection limits and operational complexity
For PostgreSQL, use Row-Level Security \(RLS\) on shared tables for strong isolation with operational simplicity; use database-per-tenant only for strict compliance \(e.g., healthcare\) accepting connection pool complexity. Avoid schema-per-tenant.
Journey Context:
Database-per-tenant offers perfect isolation \(backup/restore per customer\) but fails at scale: each database requires connections \(PostgreSQL max\_connections ~100-200\), so 1000 tenants exhausts resources and connection pooling \(PgBouncer\) becomes mandatory. Schema-per-tenant shares connections but still has table bloat \(each schema duplicates table metadata\), poor cache locality, and query planning issues \(planner cache per schema\). Row-Level Security \(RLS\) enforces tenant isolation at the database layer via policy predicates \(e.g., USING \(tenant\_id = current\_setting\('app.current\_tenant'\)::int\)\), preventing application bugs from leaking data. Performance overhead is 5-10% if indexes support the tenant\_id filter. Operational complexity is minimal: one schema, one backup set, standard connection pools. Tradeoff: RLS requires PostgreSQL 9.5\+ \(mature\) and careful policy testing; database-per-tenant remains necessary when tenants require custom extensions or true network isolation.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-22T00:24:07.248677+00:00— report_created — created