Multi-Tenancy: The Choices You Cannot Easily Undo
Last updated:
Three models, in ascending order of cost
| Model | Isolation | Operational cost | Fits |
|---|---|---|---|
| Shared schema, tenant column | Logical | Lowest | Most SaaS products |
| Schema per tenant | Moderate | Medium | Tens to low hundreds of tenants |
| Database per tenant | Strong | Highest | Regulated or very large enterprise customers |
Start with the first unless a specific, named requirement forces otherwise. Moving from shared to isolated later is work; starting isolated and discovering you cannot afford to operate it is worse.
Enforce scoping in one place
The catastrophic failure in multi-tenant systems is one query that forgets its tenant filter and returns another customer's data. It happens through ordinary human error, usually in a hurried fix.
Do not rely on developers remembering. Enforce tenant scoping at the data-access layer so that an unscoped query is impossible or immediately obvious — a base query object, a row-level security policy, or both.
Then test it adversarially: automated tests that attempt cross-tenant access and must fail. Run them on every deployment.
Plan for the noisy neighbour
One tenant importing a million records should not slow everyone else down. In shared infrastructure this needs deliberate design: queue work per tenant, rate limit per tenant, and put heavy jobs on separate workers.
This is easy to add early and painful to retrofit once a large customer is already causing the problem you are trying to solve.
Tenant-specific configuration without tenant-specific code
Customers will ask for their own workflow, their own fields, their own rules. Say yes through configuration, never through branching code. The moment you have if tenant == 'bigcorp' in the codebase, you have started maintaining several products.
- Configurable fields and forms rather than bespoke schemas
- Feature flags per tenant for gradual rollout
- Configurable workflow steps within a defined framework
- A hard organisational rule that bespoke work becomes a configurable capability or does not happen
Data residency arrives sooner than you expect
The first enterprise or European customer will ask where data is stored. If the architecture assumes a single region, the answer is an expensive project rather than a configuration change.
You do not need multi-region on day one, but the design should not preclude it: keep region as a property of a tenant even if every tenant is currently in the same one.
Migrations and backups get harder with tenants
Schema migrations must work across every tenant, including the one with ten million rows and the one that signed up yesterday. Test migrations against a copy of your largest tenant, not a development database with fifty records.
Backups need to be restorable per tenant. “We restore everything to yesterday” is not an acceptable answer when one customer deletes a project by mistake, and discovering that during the incident is the wrong time.
Frequently asked questions
Can we start shared and isolate a customer later?
Is row-level security enough?
How do we handle a customer who wants their data deleted?
What about per-tenant customisation requests during sales?
Designing a platform that will have real customers on it?
These decisions are cheap now and expensive in two years. Happy to review your architecture plan before you commit to it.
Related services
What we build for problems like this one