Multi-tenancy is the architectural decision that defines a SaaS product's scalability ceiling and operational cost floor. Get it right and you can serve thousands of enterprise customers from a single deployment. Get it wrong and you face a years-long migration with live customers depending on the system.
This is not a decision to make casually. It shapes the database schema, the authentication layer, the deployment model, and the compliance posture of the entire platform.
The Three Isolation Models
1. Silo (Per-Tenant Database)
Each customer gets their own isolated database instance. Data is physically separated — there is no schema-level query that can accidentally leak cross-tenant data.
Advantages:
- Maximum data isolation — ideal for heavily regulated industries (finance, healthcare, legal)
- Independent backup, restore, and disaster recovery per tenant
- Customisable database configuration per tenant (useful for enterprise contracts)
- Compliance certifications (SOC 2, HIPAA, GDPR) are easier to scope
Disadvantages:
- High operational overhead at scale — managing 500 database instances is a different discipline from managing one
- Schema migrations must be applied across all tenants — requires a migration orchestration layer
- Higher infrastructure cost for small tenants (you are paying for idle capacity)
- Cross-tenant analytics require federated queries across multiple databases
This model suits enterprise SaaS with a small number of high-value clients, strict compliance requirements, or where custom data residency by geography is required.
2. Bridge (Shared Database, Separate Schema)
All tenants share a single database engine, but each tenant has their own schema namespace (in PostgreSQL: `CREATE SCHEMA tenant_<id>`). Tables are duplicated per tenant within the schema.
Advantages:
- Reasonable isolation — cross-tenant queries require explicit schema-crossing
- Schema migrations can be batched but still applied per-tenant
- Better resource utilisation than silo model
- Easier cross-tenant reporting than pure silo
Disadvantages:
- Schema sprawl at scale — thousands of schemas become difficult to manage
- Most ORMs and query builders do not handle dynamic schema selection elegantly
- Connection pooling complexity increases
- PostgreSQL has practical limits on schema count
This model works well in the mid-range: tens to low hundreds of tenants, with meaningful isolation requirements but not the regulatory demands of silo.
3. Pool (Shared Database, Shared Schema)
All tenants share tables, with a `tenant_id` column on every row used to filter data. Row-Level Security (RLS) at the database level enforces the isolation.
Advantages:
- Single schema to migrate — dramatically simpler operations
- Best resource utilisation — small tenants share infrastructure cost
- Easiest to build cross-tenant analytics
- Scales to thousands of tenants without operational overhead
Disadvantages:
- Data isolation is enforced at the application and database query level — a missing `WHERE tenant_id = ?` clause is a data breach
- RLS policies must be comprehensive and audited regularly
- Query performance degrades if tenant_id is not indexed correctly across large tables
- Compliance auditors require more rigorous access control evidence
This is the model most modern SaaS platforms use, and for good reason — operational simplicity and infrastructure cost at scale are compelling. The risk is in the engineering discipline required to enforce tenant boundaries consistently.
Implementing Pool Model Correctly
If you choose the pool model (and for most B2B SaaS products, you should), the implementation details determine whether the isolation is real or illusory.
Row-Level Security in PostgreSQL
PostgreSQL's RLS is the strongest defence. Rather than relying on application-level WHERE clauses, enforce tenant filtering at the database level:
ALTER TABLE orders ENABLE ROW LEVEL SECURITY;
CREATE POLICY tenant_isolation ON orders
USING (tenant_id = current_setting('app.current_tenant_id')::uuid);Set the tenant context at the start of every database session:
SET app.current_tenant_id = '{{uuid}}';With this in place, even if application code omits a WHERE clause, the database will silently filter to the current tenant's rows.
Middleware Enforcement
Every request must establish tenant context before hitting any data layer. In a Next.js / Express / Fastify application, implement this as a middleware that:
- Extracts tenant identity from the JWT or session cookie
- Validates the tenant exists and is active
- Sets the tenant context for the database connection
- Attaches the tenant object to the request context
Make this middleware non-bypassable — apply it at the router level, not per-handler.
Index Strategy
With millions of rows across thousands of tenants, index design is critical. Every table that participates in tenant isolation needs a composite index:
CREATE INDEX idx_orders_tenant_created ON orders (tenant_id, created_at DESC);Pure tenant_id indexes are useful for management queries but not for most application queries, which combine tenant_id with other filter conditions.
Authentication Architecture
Multi-tenant SaaS requires careful thought about where authentication happens and how tenant context is established from it.
The most robust pattern:
- **Organisation-scoped JWT**: The JWT payload includes both `user_id` and `tenant_id`. The token is signed and validated by the auth service.
- **Token-based tenant context**: The `tenant_id` in the JWT is the authoritative source of tenant context — it is never taken from query parameters or request headers.
- **Role within tenant**: Include the user's role within the tenant (`admin`, `member`, `viewer`) in the JWT to drive authorisation decisions.
For enterprise customers requiring SSO (SAML, OIDC), the tenant is identified by the identity provider configuration — an email domain or an organisation-specific IdP URL routes the user to the correct tenant.
Infrastructure and Deployment
For most pool-model SaaS products, the infrastructure model is:
- Single application deployment (or horizontally scaled pods behind a load balancer)
- Single primary database with read replicas for analytics workloads
- Connection pooling via PgBouncer or Supabase pooler — direct connections from hundreds of application instances to PostgreSQL will exhaust the connection limit
- Redis or similar for session state — do not store session data in the primary database
At scale (thousands of active tenants, hundreds of millions of rows), consider sharding by tenant cohort — a partitioning strategy where ranges of tenant IDs map to separate database instances, with an application-level routing layer directing queries to the correct shard.
Schema Migration at Scale
This is the operational challenge that bites teams hardest. Every schema change must be:
- **Backwards compatible** — the old code must work with the new schema during the deployment window
- **Applied atomically or sequentially** — depending on the isolation model
- **Rolled back safely** — if the migration fails partway through, the system must remain functional
For pool model, running migrations against a single shared schema is straightforward — tooling like Flyway, Liquibase, or Prisma Migrate handles this. For bridge or silo models, you need a tenant migration orchestrator that applies migrations tenant-by-tenant, handles failures, and tracks per-tenant schema version.
Getting the Architecture Right
The cost of choosing the wrong multi-tenancy model is not paid at build time — it is paid 18 months later when you have enterprise customers on annual contracts and a migration that requires downtime to complete.
The decision framework is simple:
- Regulated industry, enterprise clients, data residency requirements → Silo or Bridge
- Mid-market SaaS, moderate compliance, hundreds of tenants → Bridge or Pool with strong RLS
- PLG motion, SMB focus, thousands of tenants, operational simplicity → Pool
Invest in the architecture decision early. The engineering cost of rebuilding the multi-tenancy model later is substantial — and the business cost of the downtime and customer confidence impact is higher still.