Hermes Wiki
Architecture/Challenges/design-a-multi-tenant-data-isolation-strategy

Design a Multi-Tenant Data Isolation Strategy

Scenario prompt

Design the data isolation strategy for a B2B SaaS product serving hundreds of enterprise tenants. It needs to:

  • Guarantee tenant data never leaks across tenant boundaries, even if application code has a bug
  • Support a handful of large, compliance-sensitive tenants who require dedicated infrastructure, alongside a long tail of smaller tenants who are fine on shared infrastructure
  • Let a new tenant onboard without a schema change or an infrastructure provisioning step for the common case
  • Prevent one tenant's traffic spike or expensive query from degrading performance for every other tenant on shared infrastructure

Mihir's attempt

[!todo] Write your own attempt here before reading the model solution below — which isolation model you'd default to, how you'd handle the compliance-tier tenants, and how you'd stop noisy neighbors.

Model solution

Default to a pooled model with row-level security as the backstop, not the only line of defense. For the common case (most tenants), a shared database with a tenant_id column on every table is the cheapest to operate and the fastest to onboard — no per-tenant provisioning step. But relying on application code to remember WHERE tenant_id = ? on every query is exactly the kind of thing that fails silently under a bug or a rushed migration. Database-enforced row-level security (Postgres RLS, or an equivalent policy layer) makes tenant isolation a property of the data layer itself: even a query the application forgot to scope correctly gets filtered by the database, not by application discipline. This turns "a bug leaked tenant data" from a data breach into a much smaller class of failure.

Tiered isolation: pool → bridge → silo, chosen per tenant, not fixed for the whole platform. Model the isolation spectrum as three tiers instead of a single binary choice:

  • Pool — shared database, RLS-enforced, cheapest, default for new/small tenants.
  • Bridge — shared database cluster, but each tenant (or tenant cohort) gets its own schema or dedicated connection pool, giving resource isolation without full infra duplication.
  • Silo — fully dedicated database (or entire account/VPC) per tenant, for the tenants whose compliance requirements (data residency, dedicated encryption keys, contractual isolation guarantees) demand it.

A tenant's tier is a property stored in a control-plane registry, and the application's data-access layer routes to the right database/connection based on that tier — the application code doesn't need to know or care which tier a given tenant is in beyond that routing lookup.

Noisy-neighbor containment via resource quotas at the pool/bridge layer. Per-tenant connection pool limits, query timeouts, and (where the database supports it) resource governor limits cap how much of the shared infrastructure any single pooled tenant can consume. This is a cost/complexity tradeoff against full siloing — quotas contain the blast radius without paying for dedicated infrastructure per tenant.

Tier migration has to be a supported, non-disruptive operation, not a one-way onboarding decision. Tenants grow, and a growing tenant's needs (or a new compliance requirement) can push it from pool to silo after the fact. Building the migration path (a background copy + cutover, similar in spirit to the Strangler Fig Pattern applied to a single tenant's data rather than a whole system) as a first-class, tested operation avoids the common trap where tier migration is designed only in theory and turns into a fire drill the first time it's actually needed.

Gaps to revisit

  • Testing RLS policies against regression — how do you continuously verify that every new table/migration actually has its isolation policy applied, rather than discovering the gap in a security audit?
  • Cost model at scale — at what tenant count does the bridge tier's per-schema overhead start rivaling silo cost, and does that change the default tier assignment?
  • Cross-tenant aggregate features (e.g., platform-wide benchmarking data offered back to tenants) — how do you build genuinely cross-tenant read paths without punching a hole through the isolation model built for everything else?

Principal Engineer Lens

Multi-tenant isolation is a design problem that looks like a database schema question on the surface but is really an organizational-complexity problem: it's about matching infrastructure investment to a distribution of tenant requirements that isn't uniform, and building a system where "this tenant needs stronger guarantees" is a configuration change, not a rearchitecture. The pool/bridge/silo framing is a pattern worth having ready in any review where "multi-tenant" comes up, because the naive binary answer (shared vs. dedicated) forces a false choice between cost and compliance that the tiered model avoids. This maps directly onto Fintech/Capital Markets B2B platforms, where a handful of large institutional clients routinely demand dedicated-infrastructure guarantees that would be wildly uneconomical to extend to every tenant — recognizing which tenants actually need that tier, and building the tiering as infrastructure rather than one-off exceptions, is exactly the kind of judgment that scales past any single employer's tooling.

Reel Script

Setup: You're building a SaaS product for hundreds of companies — how do you make sure Company A can never, even by accident, see Company B's data, without giving every tenant its own dedicated database?

Concept walkthrough: Start with the naive answer — a shared database with a tenant_id column — and why relying on application code to filter by it correctly, every time, on every query, is fragile. Introduce row-level security as a database-enforced backstop, then layer in the pool/bridge/silo tiering as the answer to "but some tenants need more than that."

Real example tie-in: Walk through a concrete compliance-driven tenant — a large bank client that contractually requires data residency and dedicated encryption keys — and show how it routes to the silo tier via a control-plane lookup, while a small startup customer stays on the cheap pooled tier with zero extra provisioning.

Tradeoffs & alternatives: Contrast the operational cost of full per-tenant siloing (safest, most expensive, slowest to onboard) against pure pooling (cheapest, fastest, weakest isolation guarantee without RLS) — and explain why the tiered model is a pragmatic middle path rather than picking one extreme for the whole platform.

Principal Engineer takeaway: The real skill here isn't picking one isolation model — it's recognizing that tenant requirements aren't uniform and building infrastructure that can express that as configuration (a tier assignment) instead of a one-off architectural exception every time a big client asks for more. That's the difference between a system that scales to its most demanding customer and one that has to be rebuilt every time it lands one.

Hermes Wiki