Multi-Tenant Architecture Patterns: Shared Schema vs. Schema-per-Tenant
The tenant isolation decision you make in week one is the hardest one to undo in year two. Here's how to actually choose.

Every SaaS product eventually has to answer one question: when Tenant A and Tenant B both query the same database, what actually stops A from seeing B's data? The answer you pick early is one of the most expensive things to change later.
Shared schema, shared tables
Every tenant's rows live in the same tables, distinguished by a tenant_id column, with row-level security (or an ORM-enforced filter) keeping queries scoped. Cheapest to operate, easiest to migrate schema changes across every tenant at once. The risk is concentrated in one place: a single missing tenant_id filter is a cross-tenant data leak, not a bug ticket.
Schema-per-tenant
Each tenant gets its own schema (or database) with identical structure. Isolation is enforced by the database itself, not application code — a much stronger guarantee, and the one enterprise customers with compliance requirements will often specifically ask for. The cost shows up in operations: a schema migration is now N migrations, and "how many tenants do we have" becomes a real constraint on your connection pool and backup strategy.
The hybrid that most real products land on
Shared schema for most tenants, with an escape hatch to dedicated infrastructure for the handful of enterprise accounts that need it (or pay enough to justify it). This isn't indecision — it's matching the isolation guarantee to what each tier of customer actually requires, rather than over-engineering for a startup's first 50 tenants or under-engineering for its first enterprise deal.
What actually breaks under real load
Row-level security policies that silently no-op when a background job runs without the tenant context set. Migrations that lock a shared table for long enough that every tenant feels it at once, not just the one that triggered the change. A tenant with 100x the data of everyone else quietly degrading query performance for the whole shared table.
What we've actually run into
The tenants that cause real problems are never the average ones. It's the single account with ten times normal data volume, or the one enterprise customer who needs data residency in a region you haven't built for yet. Design the isolation boundary for the outlier you'll eventually have, not just the ten identical tenants you have on day one.