Chapter 4 · Foundations
Whether you need multi-tenancy at all
Three systems that look multi-tenant and are not, the test that separates them, and what it costs to add tenancy later versus to carry it unnecessarily.
7 min read
Chapter 1 described multi-tenancy as a permanent correctness obligation. That is a reason to be sure you need it. A surprising number of products carry the full weight of tenancy to serve a shape that did not require it.
The test
A system is multi-tenant when two users of the same product must be prevented from seeing each other's data because they work for different organisations, and when a single person may legitimately belong to more than one of those organisations.
Both halves matter. The first distinguishes tenancy from ordinary per-user privacy. The second is what makes it genuinely hard, and it is the clause most designs get wrong — see Chapter 48.
Three systems that look multi-tenant and are not
Per-user data is not tenancy
A note-taking app where every user sees only their own notes has one axis of separation: the user. user_id on every row, an authorisation check, done.
-- Per-user. One owner, no membership, no roles, no invitations.
create table notes (
id uuid primary key default gen_random_uuid(),
user_id uuid not null references users(id),
body text not null
);The difference is not the column name. It is that a tenant has members — a set of users with roles, which changes over time, independently of the data. The moment a second person must see the first person's notes because they share an employer, you have crossed over.
A marketplace is not necessarily multi-tenant
Many sellers on one storefront, buyers browsing across all of them. The catalogue is deliberately shared — the product's whole value is that you can see everyone's listings. Sellers need write-scoping on their own listings and orders, which is per-user authorisation with extra roles, not tenant isolation.
The distinguishing question: is cross-tenant visibility a feature or a breach? In a marketplace it is the feature. In Meridian, a vendor seeing another vendor's customer list is a breach. Same database shape, opposite requirement.
One big customer is not tenancy
Building for a single organisation, with departments inside it that should not see each other's records, is authorisation within one tenant, not multi-tenancy. The difference shows up in three places:
| Departments in one org | Separate tenants | |
|---|---|---|
| Billing | One contract | One per tenant |
| Admin | A shared admin can see everything | No such person exists |
| Schema changes | Negotiated with one customer | Must suit all of them |
Departments are a permissions tree. Tenants are separate businesses that happen to share your servers. Modelling the first as the second gives you invitation flows, per-tenant billing and isolation tests you will never use.
What it costs to add tenancy later
The usual argument for building it in from the start is that retrofitting is expensive. It is — but it is worth knowing the actual shape of the cost, because it is not evenly distributed.
-- The migration itself is mechanical and not the hard part.
alter table products add column tenant_id uuid references tenants(id);
update products set tenant_id = (select id from tenants limit 1);
alter table products alter column tenant_id set not null;
create index products_tenant_id_idx on products (tenant_id, name);What actually costs:
- Every query. Hundreds of call sites, each needing a scope added, and the ones you miss do not fail — they return too much. This is the expensive part, and it is why Chapter 21 builds a layer where the omission is a type error.
- Identity. A
userstable where email is unique globally has to become one where a person can be a member of several tenants. If you have already shipped "log in with your email", changing it is a user-visible migration. - Every URL containing an id.
/products/4471must become tenant-scoped or tenant-checked, and the links already in people's bookmarks and emails must keep working. - Caches. Every cache key needs the tenant in it. A key without one is a cross-tenant leak that only appears under concurrency, which is the hardest class of bug to reproduce.
Items 1 and 4 are the ones that bite. Item 4 especially: it is invisible in testing, intermittent in production, and reads like a caching bug rather than a security one.
What it costs to carry it unnecessarily
Less than the retrofit, and more than people admit:
- An invitation and membership system nobody uses.
- A tenant resolver on every request, including the ones that have no tenant.
- Isolation tests that pass trivially.
- An admin surface that must now avoid being a backdoor to every tenant.
- Every new engineer learning the rules for a constraint the product does not have.
Do not build tenancy for a possible future customer. Build it when the second organisation signs, or when the product is explicitly sold as something an organisation buys for its staff.
The second clause is the real decision rule. If the sales motion is "a company buys this for its team", it is multi-tenant from day one and pretending otherwise is deferred pain. If the motion is "an individual signs up", per-user is correct until it is not.
Meridian, tested
| Test | Meridian |
|---|---|
| Separation because of different employers? | Yes — vendors are separate companies |
| Can one person belong to several? | Yes — consultants work with multiple vendors |
| Is cross-tenant visibility a feature or a breach? | Breach |
| Does each tenant have its own billing relationship? | Yes — and its own payouts |
Four for four. Meridian is multi-tenant, and the fourth row means it is also a payments platform, which is Chapter 5.
Key points
- The test has two clauses: separation because of different organisations, and one person able to belong to several. The second is what makes it hard.
- Per-user privacy is one axis and is not tenancy. Tenancy adds members, roles and invitations that change independently of the data.
- In a marketplace, cross-tenant visibility is the feature. The same schema with the opposite requirement is a different system.
- Departments inside one customer are a permissions tree, not tenants — different billing, different admin, different schema negotiation.
- Retrofitting: the
ALTER TABLEis trivial. The cost is every query, identity, every URL carrying an id, and every cache key. Cache keys are the worst because the leak is intermittent. - Carrying it unnecessarily costs an unused invitation system, a resolver on every request, trivial tests, and an admin surface that must not become a backdoor.
- Decide by the sales motion: an organisation buying for its staff is multi-tenant on day one.
Next: The platform's relationship to money — the one architectural decision that is also a licensing decision.