CodePark/ questions / Multi-tenant isolation
START PRACTICINGPRACTICE
Backend question · Auth & security › Multi-tenant isolation

Your SaaS keeps many customers (tenants) in one database. What are the ways to isolate tenants, and how do you stop one tenant from seeing another's data?

There are three common models, from strongest to cheapest:

  • A database per tenant: the strongest isolation. But migrations, backups and connection counts grow with every customer.
  • A schema per tenant: one database, with one Postgres schema per tenant. It sits in the middle.
  • Shared tables with a tenant_id column: the cheapest and most common. It is also the weakest by default, because one missing WHERE tenant_id = ... leaks data.

Controls for the shared model:

  • Take the tenant id from the authenticated session or token. Never take it from a body field or header that the client chooses.
  • Scope queries in one place. A repository layer or ORM middleware should add the tenant filter, so no handler has to remember it.
  • Add a database backstop such as Postgres Row-Level Security (RLS).
  • Put tenant_id in unique keys and foreign keys, so a row can't point at another tenant's row.
  • Scope every other store too: cache keys, file storage paths, search indexes, queues and exports.
  • Test it. Write automated tests where a user of tenant A asks for tenant B's ids and gets a 404.

Also add per-tenant rate limits, so one busy customer can't slow down the others. This is the noisy neighbour problem.

  • The models are a database per tenant, a schema per tenant, or shared tables with tenant_id.
  • The tenant id must come from the authenticated identity, never from client input.
  • Add the tenant filter in one shared layer, with RLS as a database backstop.
  • Caches, files, search indexes and queues need tenant scoping too.
  • Automated cross-tenant tests prove that isolation holds.