Multi-tenancy is usually introduced as a database topic: how do you store several customers’ data in one system? That framing produces technically defensible answers to the wrong question. Tenancy determines how you onboard, support, price, migrate, recover and explain your product. The storage model is the consequence, not the decision.
The three common models
| Model | Strength | Cost |
|---|---|---|
| Shared schema — tenant ID on every row | Cheapest to operate; simplest scaling; one migration path | Isolation depends entirely on correct queries; noisy-neighbour effects; per-tenant restore is hard |
| Schema per tenant | Clearer separation; per-tenant backup is feasible; easier customisation | Migrations multiply; connection and catalogue overhead grows with customers |
| Database per tenant | Strongest isolation; simple story for security review; per-tenant residency and restore | Highest operational cost; provisioning must be automated from day one |
Hybrids are common and often correct: shared schema for the long tail, dedicated databases for a small number of large or regulated customers. That is a legitimate architecture, provided the product code does not need to know which model a given tenant uses.
The questions that actually decide it
- What isolation will your customers require in writing — not what would feel reassuring, but what appears in their procurement and security reviews?
- Do you have data-residency obligations that vary by customer or region?
- Will one customer ever need to be restored to a point in time without affecting others?
- How different can two customers’ configurations be before you are effectively maintaining separate products?
- What is your realistic operational capacity — do you have the automation to run hundreds of databases, or the discipline to keep every query tenant-scoped?
Isolation by construction, not by discipline
Whatever model you pick, the most important property is that a developer cannot accidentally write a query that crosses tenants. Relying on every engineer remembering a filter forever is not a control. Practical approaches include enforcing tenant scope in the data-access layer, using row-level security in the database, and adding tests that specifically attempt cross-tenant access and expect failure.
The operational surface people forget
Tenancy leaks into places that are not the product: support tooling that lets staff act on behalf of a customer, background jobs that iterate across tenants, analytics pipelines that aggregate across them, and exports that could combine them. Each is a plausible route for a cross-tenant mistake, and each needs the same rigour as the main application.
Noisy neighbours are a product problem
In shared infrastructure, one customer’s bulk import can degrade everyone’s experience. Rate limiting, per-tenant quotas and queue isolation are not premature optimisation once you have paying customers with expectations — they are the difference between a slow afternoon for one account and an incident for all of them.
Changing your mind later
Moving from shared schema to dedicated databases is possible; moving in the opposite direction is usually harder because customers have come to expect the isolation. If you expect to serve regulated or enterprise buyers eventually, the cheapest insurance is to keep the tenant boundary explicit in code from the beginning, so that changing the physical model does not require changing the product.
