What is Multi-Tenant Database Architecture?

Last updated: July 2026

Multi-tenant database architecture is a design for storing many customers in one data tier, isolated by row, schema, or separate database. Those three isolation levels are the entire decision space — everything else in this topic is consequences: how migrations run, what restore costs, where the noisy neighbor lives, and how far each pattern scales.

Key takeaways

QuestionAnswer
The three patternsShared schema (tenant ID per row) · schema-per-tenant · database-per-tenant
Cloud vocabularyThe same three: pool · bridge · silo
Default choiceShared schema, unless compliance or scale forces isolation
Practical ceilingsSilo: ~100s of tenants · bridge: ~1,000 · pool: millions (sharded: unlimited)
The iron ruleEnforce isolation in the database, not in every query

The three patterns, in SQL

-- Pattern 1 · Shared schema ("pool"): one set of tables, tenant on every row
CREATE TABLE invoices (
  tenant_id uuid   NOT NULL,
  id        bigint GENERATED ALWAYS AS IDENTITY,
  total     numeric(10,2),
  PRIMARY KEY (tenant_id, id)      -- tenant leads: index- and shard-ready
);
ALTER TABLE invoices ENABLE ROW LEVEL SECURITY;
CREATE POLICY tenant_rows ON invoices
  USING (tenant_id = current_setting('app.tenant')::uuid);

-- Pattern 2 · Schema per tenant ("bridge"): one database, a namespace each
CREATE SCHEMA tenant_acme;          -- same tables, repeated per tenant

-- Pattern 3 · Database per tenant ("silo"): full physical separation
CREATE DATABASE tenant_acme;        -- strongest isolation; N of everything

On a managed backend the same guarantee is expressed without SQL: access control lives on the data itself, so isolation holds on every path — API, dashboard, or SDK:

// JavaScript / Node.js — Back4app JS SDK
// The same query for every tenant — ACLs scope results server-side
const query = new Parse.Query('Invoice');
const invoices = await query.find({ sessionToken: user.getSessionToken() });
// Only rows this tenant's role can read come back. No WHERE clause to forget.

Shared schema vs. schema-per-tenant vs. database-per-tenant

The three multi-tenant database patternsShared schema keeps all tenants in one set of tables separated by a tenant ID; schema-per-tenant gives each tenant its own namespace inside one database; database-per-tenant gives each tenant a fully separate database.

Database-per-tenant · silo

A database per tenant
full separation

Schema-per-tenant · bridge

One database
a namespace per tenant

Shared schema · pool

One set of tables
tenant_id on every row

Shared schema keeps all tenants in one set of tables separated by a tenant ID; schema-per-tenant gives each tenant its own namespace inside one database; database-per-tenant gives each tenant a fully separate database.
DimensionShared schemaSchema-per-tenantDatabase-per-tenant
IsolationLogical, per rowNamespacePhysical
Tenant ceilingMillions~Hundreds–1,000Tens–low hundreds
Cost per tenantLowestMiddleHighest
MigrationsRun once, hit everyoneRun × N, orchestratedRun × N, orchestrated
Per-tenant restoreHard (selective copy)ModerateTrivial (restore one DB)
Noisy neighborMost exposedContained somewhatEliminated
Per-tenant customizationHardestPossible per schemaEasiest
Onboarding a tenantInsert a rowCreate a schemaProvision a database

The details that bite

  • Indexing is tenant-first. tenant_id goes on every table — even where joins make it look redundant — and leads every composite index: (tenant_id, created_at), not the reverse. Every real query is scoped to a tenant; the indexes should be too.
  • Migrations multiply with isolation. The silo’s flexibility costs an orchestration layer: version tracking per tenant, retry logic, drift detection. Teams underestimate this more than any other line in the table.
  • Row-level security has operational fine print. Policies key off per-connection settings, which interact with connection pooling modes — set the tenant per transaction, and test the pooler. Also audit which roles bypass RLS; superuser paths are the classic hole.
  • Connection arithmetic. A pool per tenant-database exhausts connections fast; shared-schema designs share one pool — another quiet advantage of the pool pattern that surfaces only at scale.
  • Restore asymmetry drives tiering. “Can you restore just us to yesterday?” is an enterprise contract question; if the answer must be yes, that tenant belongs in a silo — which leads directly to the hybrid.

Scaling and the hybrid end-state

The growth path for the pool pattern is sharding by tenant: several shared-schema databases, each holding a slice of tenants, with a catalog mapping tenant → shard (open-source Citus built this into PostgreSQL, including moving a hot tenant to its own node). Combined with tiering, this yields the architecture most mature SaaS converges on: the free tier pooled, mid-size tenants pooled across shards, and the few regulated or enormous tenants siloed — with tenant_id kept in every schema everywhere, so any tenant can move between tiers without a remodel. Tenant mobility is the property to design for on day one; it is nearly impossible to retrofit.

Common use cases

  • B2B SaaS. The defining case: every workspace, org, or team in your product is a tenant in one of these patterns.
  • Freemium products at scale. Thousands of small free tenants pooled at near-zero marginal cost — the economics that make free tiers possible.
  • Regulated verticals. Health, finance, and legal customers contractually requiring silos — served from the same codebase via the hybrid.
  • Agencies and platforms. One application serving many client organizations, each with its own boundary.
  • Internal multi-team platforms. Departments as tenants on shared tooling — same patterns, friendlier threat model.

Which pattern should you choose? A decision matrix

Choose shared schema when…Choose schema-per-tenant when…Choose database-per-tenant when…
Tenants are many and smallTenants number in the hundredsTenants are few and large
Cost per tenant must approach zeroModerate isolation is worth some opsCompliance demands physical separation
One migration should update everyonePer-tenant schema tweaks are neededPer-tenant restore is contractual
Self-serve signup, instant onboardingTenants onboard at human speedEach tenant justifies provisioning
You’ll shard when you growYou’ll cap tenant countYou’ll automate migrations × N

And the meta-answer: pick per tier, not per company — hybrid designs put each tenant in the cheapest pattern that satisfies its requirements, and move them as requirements change.

Limitations and trade-offs

  • Shared schema: the strongest need for database-enforced isolation — one missed filter is a breach, which is why RLS or data-layer ACLs are non-negotiable, not optional hardening.
  • Schema-per-tenant: the awkward middle — migration orchestration like the silo, isolation weaker than the silo, and database metadata limits arriving surprisingly early.
  • Database-per-tenant: everything × N — migrations, backups, monitoring, connections, cost — plus cross-tenant analytics becoming a data-engineering project.
  • All three: tenant context invades everything (queries, caches, jobs, logs), and cross-pattern moves are expensive without day-one ID discipline: globally unique identifiers and tenant_id columns everywhere, even in silos.

Multi-tenant data on Back4app

Back4app is an open-source Backend-as-a-Service (BaaS) platform that combines a managed database, auto-generated REST and GraphQL APIs, authentication, file storage, and Cloud Code serverless functions. Its answer to this article’s iron rule — enforce isolation in the database — is per-object ACLs, per-tenant roles, and class-level permissions, checked by the platform on every request from every surface, as shown in the code tabs above. That is the shared-schema pattern with the WHERE-clause risk removed; the engineering deep-dive on row-level security walks the full pattern on a document database, and the hosting-level view of the same topic covers the infrastructure tier above it.

Frequently asked questions

What are the three multi-tenant database patterns?

Shared schema — one set of tables, every row carrying a tenant identifier; schema-per-tenant — one database, a separate namespace of tables per customer; and database-per-tenant — full physical separation. Cloud architecture guides name the same three pool, bridge, and silo. Real systems increasingly mix them, tiering tenants across patterns by size and compliance needs.

Shared database or database-per-tenant — which should I choose?

The consensus default is shared schema unless something forces isolation: regulatory requirements, contractual data separation, heavy per-tenant customization, or single tenants big enough to need their own resources. Shared schema maximizes density and minimizes operations; per-tenant databases maximize isolation and multiply everything else — migrations, backups, connections, cost.

How many tenants can each pattern handle?

The practical ceilings from production experience: database-per-tenant runs comfortably to tens or low hundreds of tenants before operations dominate; schema-per-tenant reaches the hundreds to around a thousand before metadata and migration orchestration strain; shared schema scales to thousands or millions of tenants, and sharding the shared schema by tenant extends it effectively without limit.

How do you prevent one tenant seeing another tenant's data?

Defense in depth, never a WHERE clause alone. Application-level tenant scoping (middleware or ORM filters) is the first layer; database-enforced row-level security is the second — policies that filter every query by the current tenant regardless of what the application forgot. In shared-schema designs, a single missed filter is a cross-tenant breach, which is why the database itself should enforce the boundary.

How do schema migrations work across the patterns?

In shared schema, one migration updates every tenant at once — simple, with a blast radius to match. In schema- or database-per-tenant, the same migration must run once per tenant: hundreds of executions needing orchestration, version tracking, and drift detection, since a failed run leaves one tenant on an older schema. Migration tooling is the hidden tax of isolation.

Can you restore a single tenant's data?

In database-per-tenant, trivially — restore that database to any point in time, touching nobody else. In shared schema it is genuinely hard: the backup contains everyone, so you restore to a side instance and selectively copy the tenant's rows back. Per-tenant restore is one of the strongest practical arguments enterprises make for isolation tiers.

How should you index a shared-schema multi-tenant database?

Put the tenant identifier on every table — even where it looks redundant — and lead your composite indexes with it, so every query pattern becomes tenant-first. Making the tenant column the leading part of the primary key also pre-arranges the data for sharding by tenant later, which is the standard growth path.

What is sharding by tenant?

Splitting a shared-schema design across multiple databases, with all of one tenant's rows living on exactly one shard and a catalog mapping tenants to shards. It preserves shared-schema density while capping any single database's size, and enables moving hot tenants to quieter shards. The price is the catalog, rebalancing tooling, and the loss of trivial cross-tenant queries.

Related terms

Compare with

Further reading

Ready to build your backend?

Start your project on Back4app in minutes — database, auth, APIs, and Cloud Code included. No credit card required.

Written and reviewed by Back4app Engineering, Back4app Engineering · Published 2026-07-24