Library · SaaS architecture
Multi-tenant SaaS architecture.
The problem
A SaaS product serves many customers from shared infrastructure. Tenancy is the question of how strongly each customer’s data is isolated - and it is the single architecture decision that is nearly free at the start and brutally expensive to reverse at customer two hundred. Choose casually and you will meet it again during your worst week.
The architecture
Our default: row-level tenancy. Every table carries a tenant_id; PostgreSQL row-level security policies enforce isolation at the database - not only in application code - and the query layer adds a second guard. Redis keys are namespaced per tenant. Billing, quotas and metering hang off the same tenant spine.
The three options, honestly
Row-level (shared schema)
Advantages: lowest unit cost; one schema to migrate; pooled connections; trivial cross-tenant analytics for you as the operator. Disadvantages: isolation depends on discipline - RLS policies and reviews must be airtight; noisy-neighbour risk shows at the query level; per-tenant restore is surgery, not a click.
Schema-per-tenant
Advantages: stronger blast-radius containment; per-tenant restore and migration become tractable; some compliance conversations get easier. Disadvantages: migrations multiply by tenant count; connection pooling degrades; tooling must be built to manage hundreds of schemas - operational cost compounds forever.
Database-per-tenant
Advantages: maximum isolation; per-tenant tuning, regions and backup schedules; the cleanest answer to strict regulatory isolation. Disadvantages: highest cost floor per customer; fleet operations (upgrades, monitoring, migrations) become your day job; cross-tenant queries essentially disappear.
Tradeoffs we accept
Row-level tenancy trades the strongest possible isolation for operational simplicity and unit economics - the correct trade for almost every B2B SaaS before enterprise procurement demands otherwise. We design the tenant spine so a single high-value tenant can later be promoted to a dedicated schema or database without re-architecting the product: the escape hatch is planned on day one, used only when a contract pays for it.
Technology selection
PostgreSQL because RLS makes the database a second line of defence (see the ADR); Redis for per-tenant hot paths; connection pooling sized for shared-schema access. The full platform context is on the architecture page.
Related: SaaS Development service · Caching strategy · Engineering decisions · FinCalix case study