Skip to content

Multi-Tenancy Patterns That Survive Real Customers

{ BLOG DETAILS }

Shared schema, schema-per-tenant, database-per-tenant. The choice is cheap on day one and expensive to reverse on day four hundred — here is how to make it once.

Multi-Tenancy Patterns That Survive Real Customers

Introduction

Shared schema, schema-per-tenant, database-per-tenant. The choice is cheap on day one and expensive to reverse on day four hundred — here is how to make it once.

SaaS

October 3, 20264 min read

Project Help

Share Article

SaaSArchitecture

Multi-tenancy is the first architectural decision in any SaaS product and the one most teams make by accident. Someone adds a tenant_id column in week one, and four hundred days later an enterprise prospect asks where their data physically lives, and the answer turns into a quarter of engineering work.

There are three patterns worth considering. Each is correct for a different business, and the thing that should decide between them is not elegance — it is what your customers will contractually require.

Pattern one: shared schema

Every tenant's rows live in the same tables, separated by a tenant column and enforced by row-level security or a query layer that refuses to build a query without a tenant filter.

Choose it when you have many small tenants, self-serve signup, and no customer who will demand physical isolation. It is the cheapest to operate: one database to back up, one migration to run, one connection pool.

The risk is that a single missing filter leaks one customer's data to another, and that class of bug is invisible in testing because your test data usually has one tenant. The mitigation is structural, not procedural: enforce isolation in the database with row-level security, so a forgotten WHERE clause returns nothing rather than everything.

Pattern two: schema per tenant

Each tenant gets its own schema inside one database. Isolation is real at the query level, backups can be taken per tenant, and a customer can be exported or deleted without touching anyone else's rows.

Choose it when you have tens to low hundreds of tenants, each reasonably large, and you need per-customer export or deletion without heroics.

The cost is migrations. Every schema change has to run across every schema, and it has to be safe to run halfway. Teams that pick this pattern without building migration tooling first end up afraid to change the schema at all, which is a worse problem than the one they were solving.

Pattern three: database per tenant

Full physical separation. Each customer gets a database, sometimes in a region they choose.

Choose it when you sell to enterprises, healthcare, or the public sector, where data residency is in the contract rather than in the FAQ. It is also the only pattern where "delete our data" is a one-line operation you can prove.

The cost is operational and it is not small: provisioning, connection management, per-tenant monitoring, and a deploy process that has to reason about a fleet rather than a database. Do not choose this because it sounds safest. Choose it because a contract requires it.

The decision, in one question

Ask: what is the largest customer we realistically want in the next three years, and what will their security review require? If the honest answer is "small businesses on a credit card", shared schema. If it is "a hospital group" or "a bank", you are heading for database-per-tenant, and building shared-schema first means doing the work twice.

The middle ground — schema per tenant — is genuinely good for B2B products selling to mid-market companies, which is most of what we build. It is what sits behind our clinic management platform.

Things that bite regardless of pattern

  • Noisy neighbours. One tenant running a huge report should not slow everyone else down. Budget for per-tenant rate limits before a customer finds the limit for you.
  • Cross-tenant features. Admin dashboards, aggregate analytics and support tooling all need to read across tenants. Design that path deliberately, with its own audit trail — it is the most dangerous code in the system.
  • Tenant lifecycle. Creating a tenant is easy. Suspending, merging, renaming and deleting one are the operations nobody specifies and everybody eventually needs.
  • Per-tenant configuration. Feature flags, branding, tax rules. Keep this in data rather than in code, or every new customer becomes a deploy.

Migrating later is possible, but price it honestly

Moving from shared schema to schema-per-tenant is a real project: a dual-write period, a backfill, a cutover, and a rollback plan. It is perfectly doable — we have done it — but it typically costs more than the entire original build of the tenancy layer, and it lands at the worst possible moment, because what triggers it is usually a deal you want to close this quarter.

That is the whole argument for spending a week on this in discovery. More on that in what custom software actually costs.

Where to go next

Billing is the other decision with the same irreversibility profile — subscription billing: the edge cases that break SaaS products covers it. If you are choosing a partner for the build, how to choose the right SaaS development partner is the place to start.

Or talk it through with us: we do this design work as a standalone engagement as well as part of a build. See SaaS platform development, or send us the problem.

Building something like this?

Tell us what you are trying to ship and by when. We will come back with a scope, a fixed estimate and the parts we think you should cut.

Start a conversation