Topic

Multi-Tenant Architecture & Data Isolation

Where the tenant boundary sits, how each request finds its tenant, and what keeps one tenant's data and load away from another's.

These guides build on each other. The first decides where the boundary between tenants is drawn; the next three make sure every request respects it; the last keeps one tenant's traffic from becoming everyone's outage. If you are reviewing an existing system rather than designing a new one, start with the leak-prevention guide: its linter lab gives you a quick count of the database calls that bypass your tenant scoping.

Suggested reading order

  1. Shared Tables, Schema per Tenant, or Database per Tenant: Choosing a PostgreSQL Isolation Model

    Choose shared tables, schemas, or databases, and see what each costs in capacity, connections, and restores.

    Lab finding: 76% less at the peak minute (594 vs. 2,482 units); average utilization 53% shared vs. 13% dedicated.

  2. Tenant Routing by Hostname: Subdomains, Customer Domains, and a Safe Resolver

    Turn each request's hostname into a tenant safely, before authentication or database work.

    Lab finding: The shortcut turned an IPv6 host into "[2001" and kept duplicate keys. Cancelling the first caller failed all 500 shared lookups; a detached context failed only that one.

  3. PostgreSQL Row-Level Security for Multi-Tenant Tables: Policies, Pools, and Bypass Rules

    Make PostgreSQL enforce the boundary when application code forgets, and know who bypasses it.

    Lab finding: A session-level SET leaked tenant A's rows to the next request, and a string-formatted SET LOCAL let tenant B read tenant A. set_config with a bind parameter prevented both.

  4. Preventing Cross-Tenant Data Leaks: Structure, Database Policies, and Probes

    Add structural linting, cross-tenant tests, and production probes around the boundary.

    Lab finding: The string rule missed queries in constants, built by concatenation, or with tenant_id only in a comment, and flagged two safe calls. The structural rule caught every unsafe call.

  5. Per-Tenant Rate Limiting: Containing Noisy Neighbors in a Shared API

    Stop one tenant's flood from consuming everyone's capacity with per-tenant limits.

    Lab finding: No limit: 24.4%. Global limit: 17.2%, because the flooder takes most tokens. Per-tenant buckets: 100%, with a 34 ms p99.

Put numbers on it: Tenant Isolation Decision Planner

All guides in this topic