Multi Tenant SaaS: What to Decide Before You Build

Multi tenancy is the set of decisions that are cheap to make on day one and expensive to change on day four hundred. Most of them are not about code. They are about what you are promising customers before you know who those customers are.

Here is what to decide up front, and what you can safely defer.

Decide the isolation model first

ModelIsolationCost and effortFits
Shared tables with a tenant column Logical, enforced in software Lowest Most SaaS, especially early
Schema per tenant Strong, one database Medium. Migrations multiply Hundreds of tenants with compliance pressure
Database per tenant Strongest Highest. Real operational weight Enterprise, regulated, or data residency rules

Start with shared tables unless a specific requirement forbids it. It is the cheapest to build, the cheapest to migrate and the easiest to reason about. The usual objection, that enterprise customers will demand physical separation, is worth taking seriously only when you have an enterprise customer asking. Designing for a buyer you have not met is how products arrive late with features nobody ordered.

What you must do on day one is make the tenant boundary explicit everywhere, so moving to a stronger model later is a migration rather than a rewrite.

Make leaking data structurally hard

Every serious multi tenant bug is the same bug: a query that forgot the tenant filter. You cannot solve this with discipline, because discipline fails at 6pm on a Friday.

Solve it with structure. Pick one and enforce it absolutely:

  • Row level security in the database. The strongest option. The database refuses to return another tenant's rows even if the application asks, so a forgotten filter returns nothing instead of returning everything.
  • A repository layer no query can bypass. Every read and write goes through code that injects the tenant scope from request context. The raw client is not reachable from feature code.

Then write the test that matters: create two tenants, create data in both, and assert that every endpoint returns only one tenant's data. Run it in CI. This single test catches the class of bug that ends companies.

The tenant is not the user

Conflating them is the most common modelling mistake and one of the most painful to undo, because the fix touches every table.

Users belong to tenants through a membership, not through a column on the user. One person may belong to several organisations with a different role in each, and they expect to keep one login. Agencies, consultants, accountants and anyone with a parent company all need this, and they are usually your best customers.

Build the join table on day one even if your first hundred users each belong to exactly one tenant. It costs an hour now and a quarter later.

Put the tenant in the request context, once

Resolve the tenant at the edge, from a subdomain, a path segment or a token claim, and put it in a request scoped context that the data layer reads automatically.

Passing a tenant id as an argument through every function is how it eventually gets dropped, usually in a background job or a webhook handler where the request context does not exist. Those two places are worth auditing specifically: they are where tenant scoping is most often forgotten, because nobody is logged in.

Decide the noisy neighbour question early

On shared infrastructure one tenant can degrade the service for everyone: a bulk import, a runaway report, an integration retrying in a loop.

Rate limit per tenant rather than per user, and put heavy work on a queue with per tenant concurrency limits. Both are far easier to add before you have traffic than during the incident, and the incident is how most teams learn they needed them.

What you can safely defer

Not everything needs deciding now. These can wait, and deferring them is the right call:

  • Per tenant customisation. Themes, custom fields, configurable workflows. Wait for the request, then build the narrow version.
  • Regional data residency. Real work, but only when a customer with that requirement exists.
  • Per tenant backup and restore. Needed eventually. Not needed before you have tenants worth restoring.
  • Usage based billing. Start with seats or a flat fee. Metering is a project of its own.

The admin console is not optional

You will need to answer "what does this customer actually see?" on your second support ticket. Build a console that lets your team view a tenant's state and, carefully, impersonate a user inside it with the action logged.

This gets cut from scope constantly and is the reason founders end up querying production by hand at midnight. It is the same argument as in our MVP cost breakdown: cheap now, ruinous later.

Frequently asked questions

What is multi tenant architecture?

One running application serving many customer organisations, with each tenant's data isolated from the others. Isolation can be logical, shared tables with a tenant column, or physical, a schema or database per tenant. The application code is shared in all three cases; only the data boundary moves.

Should I use one database per tenant or a shared database?

Shared tables with a tenant column, unless a specific requirement forbids it. It is cheapest to build, cheapest to migrate and easiest to reason about. Move to schema or database per tenant when a real customer brings a compliance or data residency requirement, not in anticipation of one.

How do I stop one tenant seeing another tenant's data?

Structurally, never by discipline. Either enable row level security so the database itself refuses cross tenant reads, or route every query through a repository layer that injects the tenant scope and make the raw client unreachable from feature code. Then add a CI test with two tenants asserting every endpoint returns only one tenant's rows.

Can a user belong to more than one tenant?

Yes, and you should assume they will. Model membership as a join table between users and tenants with a role on the membership, not as a column on the user. Agencies, consultants and anyone with a parent company need this, and retrofitting it later touches every table.

How do I handle a noisy neighbour in multi tenant SaaS?

Rate limit per tenant rather than per user, and run heavy work on a queue with per tenant concurrency caps. The usual culprits are bulk imports, large reports and an integration retrying in a loop. Both controls are much easier to add before you have traffic than during the incident.

Where do multi tenant bugs usually come from?

Background jobs and webhook handlers. Those run without a logged in user, so the request context carrying the tenant is absent and the scoping is quietly skipped. Audit those two paths specifically, and make the tenant an explicit required input to every job.

Where to start

Write the two tenant isolation test before you write the second feature. It takes an afternoon and it is the only thing on this page that prevents a category of failure you cannot apologise your way out of.

If you are already live and not sure whether that test would pass, tell us about your setup and we will tell you where to look first.

Venturial

Your product, built end to end.

Mobile apps, web platforms, payment systems and AI agents. One team, from the first call to production and the version after it.

Talk to engineeringBack to the blog