Multi-tenant architecture: the decision you cannot cheaply reverse

Three models, three sets of trade-offs, and one that is right for almost everybody at the start.

The short answer

Most SaaS products should start with a shared schema and a tenant id enforced by Postgres row-level security. It is the cheapest to build and migrate. Move to schema-per-tenant or database-per-tenant only when a specific customer contract or regulation requires physical isolation.

Key takeaways

  • Add the tenant boundary before your first customer, even if you only have one.
  • Row-level security enforces isolation in the database, not in application code you might forget.
  • Schema-per-tenant makes migrations a batch job; database-per-tenant makes them a project.
  • Enterprise buyers ask about isolation — have a written answer before the question arrives.

Tenancy is the decision most often deferred and most expensive to reverse. Every query, every permission check and every migration inherits it.

The three models

ModelIsolationMigration costFits
Shared schema + tenant idLogical, enforced by RLSOne migration for everyoneAlmost every product at the start
Schema per tenantStrong, same databaseOne migration per schema, batchedHundreds of tenants with compliance needs
Database per tenantPhysicalA migration programmeEnterprise, regulated, per-customer residency

Why shared schema wins early

One schema, one migration, one connection pool, one backup. With Postgres row-level security, isolation is enforced by the database itself: a query that forgets its tenant filter returns nothing rather than returning someone else's data. That is a materially different guarantee from remembering to write `WHERE tenant_id = ?` in three hundred places.

What it requires you to get right

  • Every table with tenant-owned data carries a tenant column, with a policy on it — no exceptions for 'small' tables.
  • The tenant context is set per request from the session, never passed in from the client.
  • Background jobs and admin tooling set the context explicitly rather than bypassing RLS by habit.
  • Tests include a cross-tenant access attempt for every new table. Once, then automatically, forever.

When to move up a level

Move when a contract requires it and the revenue justifies it — not in anticipation. A hybrid is common and perfectly respectable: shared schema for the self-serve base, a dedicated database for the three enterprise customers who pay for it.

Questions people also ask

Technically yes, practically it is a rewrite of every query, every permission check and every migration you have written. It is the single most expensive retrofit in a SaaS product, which is why we insist on the boundary existing before the first customer.

Keep reading

Related

What this connects to

Rather have this answered about your own account?

Send us what you have. We will look at it properly and write back with what we would change, in the same plain terms as the page you just read.