Data isolation is the one architectural decision in multi-tenant SaaS that's genuinely difficult to change after the fact, because it's baked into every query, every migration, and every backup and restore procedure from day one. Picking between row-level isolation, schema-per-tenant, and database-per-tenant isn't a stylistic choice — each one prevents a different class of bug and creates a different operational burden.
Row-level isolation: cheapest to run, easiest to get wrong
A single shared database and schema, with every table carrying a tenant_id column and every query filtered by it, is the cheapest model operationally — one database to back up, one schema to migrate, resource usage pooled efficiently across tenants. It's also the model where a single missing WHERE tenant_id = ? clause in application code causes a cross-tenant data leak, and that bug class is invisible in testing if your test data only has one tenant. This model needs the isolation enforced as close to the database as possible — row-level security policies in Postgres, for instance — rather than trusted entirely to application-layer discipline.
ALTER TABLE invoices ENABLE ROW LEVEL SECURITY;
CREATE POLICY tenant_isolation ON invoices
USING (tenant_id = current_setting('app.current_tenant')::uuid);
-- application sets this per connection/request, before any query runs
SET app.current_tenant = '3fa85f64-5717-4562-b3fc-2c963f66afa6';
If tenant filtering lives only in application code — every query written to include the tenant_id clause — one code path added by a developer who doesn't know the convention breaks isolation silently. Row-level security policies enforced by the database itself turn a missed filter into a query returning nothing, not a cross-tenant leak.
Schema-per-tenant: stronger isolation, migration complexity multiplies
Giving each tenant their own schema within a shared database provides real isolation at the database level — a connection scoped to one tenant's schema literally cannot see another's tables, no query discipline required. The cost shows up in operations: a schema migration now has to run against every tenant's schema individually, which means migration tooling has to handle partial failures (tenant 47's migration fails, do the other 200 proceed or roll back), and the sheer number of schemas can strain connection pooling and query planner caching at a few hundred tenants.
Database-per-tenant: the isolation regulators and enterprise customers actually ask for
A fully separate database per tenant is the strongest isolation guarantee and the easiest to explain to an auditor or a security-conscious enterprise customer — there is no shared infrastructure at the data layer that a bug could leak across. It's also the most operationally expensive: connection management, backup scheduling, and monitoring all multiply by tenant count, and a fleet of thousands of small databases has real overhead even when most of them are lightly used. This model tends to show up specifically for enterprise tiers or regulated industries within an otherwise shared-infrastructure product, rather than as the default for every tenant.
Picking the model based on your actual constraints, not a default
Row-level isolation with enforced database policies is the right default for most vertical SaaS products, because it scales operationally to thousands of tenants without a linear cost increase. Schema- or database-per-tenant becomes worth the operational cost when a specific segment of customers — usually the largest or most regulated ones — genuinely requires it contractually, at which point a hybrid model (shared infrastructure for most tenants, dedicated databases for enterprise tier) is common rather than picking one model for the entire product.
Wrapping up
There's no isolation model that's universally correct — row-level isolation is the pragmatic default if it's enforced at the database layer rather than trusted to application code, and schema- or database-per-tenant earns its operational cost only when specific customers genuinely require that level of guarantee, not as a blanket architectural choice made on day one.
Independent software engineer in Nairobi specialising in Acumatica customisations, Laravel backends, and tax fiscalisation integrations across East and Southern Africa.