Multi-tenant SaaS: the architecture decisions you can't easily undo
Most SaaS architecture choices are reversible. A few are not, and those deserve deliberate thought before the first customer signs up. In our experience three decisions dominate: how tenants are isolated, where the billing boundary sits, and how identity maps to organisations.
1. Choose the tenancy model by risk, not by fashion
There are three common models: a shared schema with a tenant_id column, a schema per tenant, and a database per tenant. Shared schema is the cheapest to operate and the easiest to get wrong. Database-per-tenant is the most isolated and the most operationally expensive.
- Shared schema + row-level security for most B2B products
- Schema-per-tenant when customers demand logical separation
- Database-per-tenant only for regulated or very large customers
Whatever you pick, enforce isolation in the database, not only in application code. PostgreSQL row-level security means a missing WHERE clause becomes an empty result instead of a data leak.
alter table invoices enable row level security;
create policy tenant_isolation on invoices
using (tenant_id = current_setting('app.tenant_id')::uuid);2. Put the billing boundary on the organisation
Users come and go; the organisation pays. Model subscriptions, seats and usage on the organisation from the start, even if your first customers are individuals. Retrofitting team billing onto a user-centric model is one of the most common rewrites we see.
3. Separate identity from membership
A person should have one identity and many memberships, each with its own role. This makes invitations, SSO and agency-style access (one user, many client workspaces) straightforward rather than painful.
Getting these three right does not make a product succeed, but getting them wrong reliably slows one down. They are worth an afternoon of whiteboarding before the first migration is written.