Engineering

The Architecture Behind Multi-Tenant SaaS

Share

Multi-tenancy is one of the most consequential architectural decisions you make when building a SaaS product. Get it wrong and you’ll be refactoring it for years. Get it right and it’s invisible infrastructure that scales gracefully.

The Three Models

There are three primary multi-tenancy models. Database-per-tenant provides the strongest isolation and the simplest application code, but becomes expensive and operationally complex at scale. Schema-per-tenant (one database, separate schemas per tenant) is the sweet spot for most SaaS products — it provides good isolation with manageable operational overhead. Shared-schema (all tenants in the same tables, distinguished by a tenant_id column) is the most operationally efficient but requires careful application-level isolation to prevent data leakage.

Our Default Stack

For most SaaS products we build, we default to schema-per-tenant in PostgreSQL. Each tenant gets their own schema, and tenant routing happens at the application connection layer. Migrations run across all schemas using a schema enumeration approach. This gives us the isolation of database-per-tenant without the operational overhead.

The Authentication Layer

Tenant identification happens at the subdomain level (customer.yourapp.com) or via JWT claims. Every authenticated request carries a tenant context that gets injected into the database connection before any queries run. We use a middleware layer to enforce this — it’s impossible to make a query without tenant context, which means cross-tenant data leakage requires actively breaking the middleware, not just forgetting to add a WHERE clause.

admin