How is multi-tenant different from single-tenant?
In a single-tenant deployment, each customer gets their own instance of the application and their own database. Isolation is a property of the infrastructure: two customers cannot see each other's data because there is no path between the two deployments.
In a multi-tenant deployment, one instance serves everyone and every query carries a tenant identifier. Isolation becomes a property of the code — which is cheaper to operate and much easier to get catastrophically wrong.
The economics are why almost all SaaS is multi-tenant. Upgrading one deployment is an afternoon; upgrading four hundred is a department. But the trade is real: in single-tenant, a bug leaks one customer's data to nobody. In multi-tenant, one missing WHERE clause leaks everyone's data to anyone.
What are the three isolation models?
The choice is not binary. There are three common models, and mature products often run more than one at once — pooled for the long tail, isolated for the enterprise accounts that ask for it in procurement.
| Model | How it works | Strengths | Weaknesses |
|---|---|---|---|
| Pooled | Shared schema, tenant_id column on every row | Cheapest per tenant; one migration for everyone; instant onboarding | Isolation depends entirely on query correctness; noisy-neighbour effects; per-tenant restore is hard |
| Bridge | Shared database, one schema per tenant | Real database-level separation; per-tenant backup is straightforward | Migrations run N times; schema count becomes an operational limit in the low thousands |
| Silo | One database — or one full stack — per tenant | Strongest isolation; per-tenant tuning, residency, and restore; easiest compliance story | Highest cost per tenant; slowest onboarding; upgrade fan-out |
How do you stop one tenant reading another's data?
Every cross-tenant data leak in a pooled model has the same root cause: somewhere, a query ran without its tenant filter. Application-layer discipline alone does not prevent this, because it only takes one new endpoint written on a Friday.
The defence that works is to make the filter impossible to omit, by pushing it below the application code:
- Row-level security in the database, so the engine itself refuses rows outside the current tenant context even if the query forgot to ask
- Tenant context resolved once, at the edge of the request, and never taken from a parameter the client can set
- A repository layer that has no method capable of expressing an unscoped query — if you cannot write it, you cannot ship it
- Automated tests that authenticate as tenant A and assert 404 rather than 403 on tenant B's identifiers, because 403 confirms the record exists
- Per-tenant encryption keys where the data justifies it, so a query-level mistake still yields ciphertext
What breaks first as a multi-tenant system grows?
The failures are predictable and they arrive in roughly this order. Knowing the sequence is most of the value of having built one before.
First, the noisy neighbour. One tenant imports a million rows and everyone's dashboards slow down. The fix is per-tenant rate limits and quotas, and it needs to exist before you need it.
Second, the schema migration. A change that was instant across ten tenants locks a table across ten thousand. Migrations become a two-phase exercise — expand, backfill, contract — where the schema is always compatible with both the old and new code.
Third, the customisation request. An important customer needs a field, a workflow, a report that nobody else wants. Say yes carelessly a few times and the shared codebase quietly becomes a hundred codebases behind feature flags. The disciplined answer is a configuration and extension model designed early — custom fields, per-tenant settings, webhooks — so that 'yes' stays cheap.
Fourth, the per-tenant restore. A customer deletes something important and asks for it back. In a pooled model, restoring one tenant from a backup that contains everyone is genuinely hard, and the time to discover that is not during the incident.
When should you not build multi-tenant?
When you have three customers, multi-tenancy is architecture you are paying for before you need it. Three deployments are manageable by hand, and building the tenancy layer first is a common way to spend six months not learning anything about your market.
It is also the wrong default where data residency or regulatory separation is a hard requirement — health records in some jurisdictions, financial data under certain regulators, government contracts that specify a dedicated environment. There the silo model is not a cost problem to be optimised away, it is the requirement.
The practical middle: design the data model with a tenant identifier on day one, so the path to pooling stays open, but do not build the pooling machinery until the tenth customer makes it cheaper than the alternative.
Sources
- Multitenant architecture — tenancy models and trade-offs — Microsoft Learn
- PostgreSQL row-level security policies — PostgreSQL
- OWASP Top 10 — broken access control — OWASP
- The Twelve-Factor App — configuration and backing services — 12factor.net