Multi-tenancy is the architectural property that allows a single SaaS platform to serve multiple customers — tenants — from the same codebase and infrastructure, while keeping each tenant's data isolated from every other.
It sounds like a technical detail. It is not. The multi-tenancy strategy you choose at the start of your SaaS product shapes your security model, your compliance posture, your database performance at scale, your operational complexity, and how much it costs to run the platform per customer. Getting it wrong is one of the most expensive SaaS architecture mistakes a founder can make — because fixing it in production, under live load, with real customer data, is genuinely hard.
This guide explains the three standard approaches, when each one is right, and the specific failure modes to avoid.
Why multi-tenancy is not optional
Some early-stage founders skip the multi-tenancy question entirely. They build their first version as a single-tenant application — one database, one deployment, one customer conceptually — and defer the question of isolation.
This approach works at one customer. It starts to break at ten. By the time you have fifty or a hundred customers, the absence of a real multi-tenancy strategy tends to manifest as either a data leak, a performance problem, a compliance failure, or all three at once.
The time to make this decision is before you write the first line of product code. The decision is cheap to make early. It is extremely expensive to change later.
Strategy 1: Shared schema with row-level isolation
In a shared-schema approach, all tenants share the same database tables. Each row is stamped with a tenant identifier — typically a tenant_id foreign key. Application-level logic filters every query to return only rows belonging to the current tenant's session.
This is the most common approach, and the most commonly implemented incorrectly. The failure mode is partial or inconsistent enforcement: a developer forgets a WHERE tenant_id = ? clause on one query, and a tenant sees another tenant's data. This is not a theoretical risk. I have seen it in production multiple times.
The correct implementation uses database-level row-level security policies — available in PostgreSQL, and partially in MySQL/MariaDB — rather than relying on application-level filtering alone. With RLS, the database engine enforces the isolation constraint at the query level, regardless of whether the application remembers to include the filter. Application-level filtering can still be applied as an additional layer, but the database is the authoritative enforcement point.
Shared schema with RLS is the right choice for most SaaS products at the early stage. It is simple to operate, cost-effective (a single database serves all tenants), and scales to hundreds or thousands of tenants without infrastructure changes.
The trade-off: all tenants share query performance. A large, resource-intensive tenant will affect query times for smaller tenants on the same database unless you implement query isolation or tenant-level resource limits.
Strategy 2: Schema-per-tenant
In a schema-per-tenant approach, each customer gets their own schema within a shared database. In PostgreSQL, a schema is a namespace within a database — it has its own set of tables, but uses the same underlying connection pool and storage.
Schema-per-tenant provides stronger logical isolation than row-level filtering: a query against one tenant's schema cannot accidentally access another tenant's tables. It also makes tenant-specific customisation easier — you can, in theory, run different schema versions for different tenants.
The cost is operational complexity. At ten tenants, managing separate schemas is manageable. At five hundred tenants, database migrations become significantly more complex — you are running the same migration across hundreds of schemas, which requires tooling and discipline that most early-stage teams do not have.
Schema-per-tenant is a reasonable choice when you have a small number of large enterprise customers who require strong logical data separation but do not justify entirely separate infrastructure. It is usually the wrong choice for a high-volume SaaS with many small customers.
Strategy 3: Database-per-tenant
In a database-per-tenant approach, each customer gets their own database instance. Isolation is complete at the infrastructure level — there is no shared storage, no shared connection pool, and no mechanism by which one tenant's data could appear in another tenant's queries.
This is the strongest isolation model. It is also the most expensive and operationally complex. Each new customer requires provisioning a new database, configuring backups, applying security patches, and running migrations — multiplied by every customer you have.
Database-per-tenant is appropriate in three situations: when your enterprise customers contractually require infrastructure-level data isolation; when your compliance requirements (financial services, healthcare, government) mandate it; or when your customers are large enough that each genuinely needs dedicated database resources. It is almost never the right starting point for an early-stage SaaS.
Choosing the right strategy
For most SaaS products at the seed or early stage, the decision is straightforward: start with shared schema and row-level security, implemented at the database level.
It is the cheapest to operate, the simplest to migrate data within, and the easiest to reason about as the team grows. The performance trade-off can be addressed with good indexing — always include tenant_id as the leading column in composite indexes on tables that will be queried per-tenant.
Schema-per-tenant becomes worth considering when you are targeting mid-market or enterprise buyers who ask about data isolation during procurement, but who are not large enough to justify dedicated infrastructure. It is also worth considering if you need to run tenant-specific data customisations.
Database-per-tenant is reserved for specific regulatory requirements or very large enterprise contracts where the economics justify it.
The most important thing is to decide, implement it properly, and enforce it consistently from the start. A half-implemented row-level isolation strategy that relies on application developers remembering to include the tenant filter is not a multi-tenancy strategy. It is a data breach waiting to happen.
The indexing problem most founders miss
Regardless of which multi-tenancy strategy you choose, indexing strategy directly determines whether your platform performs well under load.
In a shared-schema SaaS, the most common performance problem I see is tables with indexes that do not include tenant_id. A query filtering by tenant_id and a secondary field — say, tenant_id and status — needs a composite index with tenant_id leading. Without it, PostgreSQL will either scan the entire table or use an index that does not account for the tenant filter, returning far more rows than needed before filtering.
The fix is simple: every table that will be queried in a tenant context should have composite indexes that include tenant_id as the first column. This is cheap to add during initial development and very expensive to add correctly in production on a large dataset.
What multi-tenancy decisions unlock
A well-designed multi-tenancy architecture is not just a technical requirement. It is a commercial asset.
Enterprise buyers ask about data isolation during procurement. A SaaS platform that can demonstrate row-level security at the database layer, tenant-scoped API tokens, and a documented isolation model will close deals that a platform without these properties will not. I have seen this distinction be worth hundreds of thousands of pounds in ARR for a single enterprise deal.
Getting multi-tenancy right is one of the most leveraged investments an early-stage SaaS can make. It removes a class of risk, enables a class of customer, and avoids a class of operational problem that will otherwise consume disproportionate engineering time as you scale.