---
title: "Database Per Tenant vs Shared Schema: Multi-Tenant SaaS Guide"
author: "Nate Laquis"
author_role: "Founder & CEO"
date: "2027-01-11"
category: "Technology"
tags:
  - multi-tenant SaaS architecture
  - database per tenant
  - shared schema database
  - SaaS data isolation
  - PostgreSQL multi-tenancy
excerpt: "Most SaaS teams default to shared schema because it feels simpler. That decision will cost some of them six figures in migration work when their largest customer demands data isolation."
reading_time: "14 min read"
canonical_url: "https://kanopylabs.com/blog/database-per-tenant-vs-shared-schema-multi-tenant-saas"
---

# Database Per Tenant vs Shared Schema: Multi-Tenant SaaS Guide

## Multi-Tenancy Is a Business Decision, Not Just a Technical One

Every SaaS product needs to answer one fundamental question early: how do you store data for multiple customers in the same system? The two dominant approaches are database per tenant (each customer gets their own isolated database) and shared schema (all customers share tables, separated by a tenant_id column). Both work. Both scale. And picking the wrong one for your specific business can burn six to twelve months of engineering time fixing it later.

This is not an academic exercise. Your multi-tenancy model affects pricing, compliance posture, operational costs, and onboarding speed. A B2B SaaS selling to 50 enterprise clients with strict data residency requirements has very different needs than a self-serve product with 10,000 small teams.

We have built multi-tenant systems for over 60 SaaS companies. The pattern we see repeatedly is teams picking shared schema by default, then scrambling to retrofit isolation when a whale customer shows up with a SOC 2 audit questionnaire. The reverse happens too: teams over-engineering database-per-tenant from day one, then drowning in operational complexity at 500 tenants. Both mistakes are avoidable if you understand the tradeoffs before writing your first migration.

![Server room with database infrastructure supporting multi-tenant SaaS applications](https://images.unsplash.com/photo-1558494949-ef010cbdcc31?w=800&q=80)

## Shared Schema: The Default Path and Why It Works

Shared schema multi-tenancy means every tenant's data lives in the same tables. You add a tenant_id column to every table, and every query includes a WHERE tenant_id = ? filter. It is the most common approach for SaaS products, and for good reason.

### How It Works in Practice

Your users table, your orders table, your invoices table all contain rows from every customer. A single PostgreSQL or MySQL instance serves all tenants. Your application layer handles routing by injecting the tenant_id into every query. ORMs like Prisma, Drizzle, and Django's ORM all support this through middleware or default scopes. Row Level Security (RLS) in PostgreSQL adds database-level enforcement so even a bug in your application code cannot leak data across tenants.

With Supabase or raw PostgreSQL, you can set up RLS policies that automatically filter rows based on the authenticated user's organization. Your application code does not need to remember to add the tenant filter. The database handles it.

### Why Teams Choose Shared Schema

- **Simple operations:** One database to back up, monitor, and upgrade. One connection pool. One migration pipeline. If you are a team of 2-5 engineers, this simplicity is not a luxury, it is a survival requirement.

- **Efficient resource usage:** A single RDS instance (db.t4g.medium at $50/month) can serve 1,000 tenants. Database-per-tenant would require either 1,000 separate instances or a complex pooling layer.

- **Fast onboarding:** Creating a new tenant is an INSERT into your tenants table. No database provisioning, no connection string management, no DNS configuration. Sub-second tenant creation.

- **Cross-tenant analytics:** Running aggregate queries across all tenants (for your internal dashboards, billing calculations, or usage metrics) is trivial. It is just a SQL query without the tenant_id filter.

- **Schema consistency:** Every tenant runs the same schema version. You deploy one migration and every customer is updated. No version drift.

### The Real Costs of Shared Schema

Shared schema is cheap at small scale. A single Supabase Pro instance ($25/month) or Neon Pro ($19/month) handles your first few hundred tenants. At scale, you will need read replicas ($100-300/month each) and eventually sharding, but most SaaS products never reach that point. For context, a well-indexed PostgreSQL instance on 8 vCPUs / 32GB RAM (about $400/month on AWS) comfortably handles 5,000+ tenants with moderate query loads.

## Database Per Tenant: When Isolation Is Non-Negotiable

Database per tenant means every customer gets a completely separate database. This could be separate PostgreSQL instances, separate schemas within one instance (a middle ground), or separate managed database clusters. The tenant's data is physically isolated from everyone else's.

### How It Works in Practice

When a new customer signs up, your provisioning system creates a new database (or schema). Your application maintains a routing layer that maps each tenant to their database connection string. Frameworks like Django have built-in support for this via database routers. In Node.js/TypeScript, you typically maintain a connection pool per tenant or use a connection proxy like PgBouncer with per-tenant routing.

The connection routing adds complexity. You need a lookup table (often in a shared "control plane" database) that maps tenant IDs to connection strings. Every request hits this lookup first, then routes to the correct database. Caching this mapping in Redis reduces latency but adds another dependency to your request path.

### Why Teams Choose Database Per Tenant

- **Hard data isolation:** A bug in your query layer cannot accidentally expose Tenant A's data to Tenant B. The databases are physically separate. This matters enormously for healthcare (HIPAA), finance (SOC 2, PCI-DSS), and government (FedRAMP) customers.

- **Per-tenant performance tuning:** Your largest customer generating 100x the queries of your average customer? Give them a bigger database instance. No noisy neighbor problems. No shared connection pool contention.

- **Data residency compliance:** Customer requires their data in eu-west-1? Spin up their database in Frankfurt. Customer needs data in Canada? Provision in ca-central-1. Shared schema cannot offer this without sharding by region, which is its own complexity.

- **Independent backups and restores:** You can restore a single tenant's database to any point in time without affecting other customers. With shared schema, restoring one tenant's data from a backup means extracting their rows from the full backup, which is error-prone and slow.

- **Simpler per-tenant customization:** If enterprise customers need custom fields, custom indexes, or even custom stored procedures, each database can diverge independently.

![Data analytics dashboard showing database performance metrics for tenant isolation](https://images.unsplash.com/photo-1551288049-bebda4e38f71?w=800&q=80)

## The Real Cost Comparison: Shared Schema vs Database Per Tenant

Cost is usually what settles this debate. Let us run actual numbers instead of hand-waving about "it depends."

### Shared Schema Costs at Scale

500 tenants, moderate usage (roughly 1,000 queries/second aggregate):

- **Database:** AWS RDS PostgreSQL db.r6g.xlarge (4 vCPU, 32GB RAM): $370/month

- **Read replica:** Same instance class: $370/month

- **Storage:** 500GB gp3: $60/month

- **Backups:** Automated snapshots: $25/month

- **Connection pooling:** PgBouncer on a t4g.small: $15/month

- **Total: roughly $840/month**

### Database Per Tenant Costs at Scale

500 tenants, same aggregate usage. You have a few options:

**Option A: Separate RDS instances per tenant.** Even the smallest RDS instance (db.t4g.micro) is $13/month. Multiply by 500 tenants: $6,500/month just for compute. Plus storage, backups, and monitoring. Total: roughly $8,000-10,000/month. This is almost never the right approach unless every tenant is paying $500+/month.

**Option B: Separate schemas within shared instances.** You run 5-10 larger PostgreSQL instances and distribute tenants across them (50-100 schemas per instance). Compute: 8 x db.r6g.xlarge at $370/month = $2,960/month. Storage and backups: $500/month. Total: roughly $3,500/month. This is the practical sweet spot for database-per-tenant at scale.

**Option C: Serverless databases per tenant.** Neon's serverless PostgreSQL scales to zero when inactive. If 80% of your tenants are low-usage, they cost near-zero when idle. Neon's pricing starts at $0.0255/compute-hour. For 500 tenants with typical usage patterns, you might spend $1,500-2,500/month. This is the best modern option if your tenants have bursty or uneven usage.

### The Bottom Line

Shared schema is 2-5x cheaper at every scale. Database per tenant only makes financial sense when your per-tenant revenue justifies the infrastructure premium, or when compliance requirements make isolation mandatory. If your average contract value is $50/month, database per tenant is hard to justify. If your average deal is $5,000/month and customers demand SOC 2 compliance, the $3,500/month infrastructure cost is a rounding error.

## The Hybrid Approach: Schema Per Tenant on Shared Infrastructure

There is a middle path that many mature SaaS products settle on, and it deserves its own section because it combines the best of both worlds. PostgreSQL schemas (not to be confused with "shared schema" as a pattern) let you create isolated namespaces within a single database instance. Each tenant gets their own schema with their own tables, but they share the same PostgreSQL server, connection pool, and backup infrastructure.

### How PostgreSQL Schemas Work for Multi-Tenancy

In PostgreSQL, a schema is a namespace within a database. You can have tenant_acme.users, tenant_globex.users, and tenant_initech.users all in the same database. Your application sets the search_path at the connection level to route queries to the correct schema. This gives you table-level isolation without the operational overhead of managing separate database instances.

Citus (now part of Azure Cosmos DB for PostgreSQL) takes this further with distributed tables. You define a distribution column (tenant_id), and Citus automatically shards data across nodes while keeping each tenant's rows co-located. Queries with a tenant_id filter hit a single shard. Cross-tenant queries fan out across all shards.

### When Hybrid Makes Sense

This approach works well when you have 100-5,000 tenants, need stronger isolation than row-level filtering but cannot justify separate database instances, and your team has PostgreSQL expertise. Django's django-tenants library implements this pattern out of the box. For Node.js/TypeScript, you will need to build the schema routing yourself, but it is straightforward with Prisma's multi-schema support or Drizzle's dynamic schema selection.

The operational overhead falls between the two extremes. Migrations run once per schema (which can be slow at 1,000+ schemas), but backups, monitoring, and connection pooling stay simple. You get per-tenant data isolation for compliance purposes while keeping your DBA from losing sleep over managing hundreds of database instances.

If you are building a [multi-tenant SaaS architecture](/blog/multi-tenant-saas-architecture) from scratch, this hybrid approach is worth serious consideration before committing to either extreme.

## Migration Strategies and How to Switch Without Downtime

The worst-case scenario is realizing 18 months in that you picked the wrong model. The good news: migration is possible. The bad news: it is expensive and time-consuming. Here is what each direction looks like.

### Migrating from Shared Schema to Database Per Tenant

This is the more common migration direction. A large customer demands isolation, or you are entering a regulated market. The process looks like this:

- **Phase 1 (2-4 weeks):** Build the tenant routing layer and connection management. Deploy alongside your existing shared database. All traffic still hits the shared database.

- **Phase 2 (2-4 weeks):** Create the target databases for tenants being migrated. Set up CDC (Change Data Capture) using tools like Debezium or AWS DMS to replicate data from the shared database to tenant-specific databases in real time.

- **Phase 3 (1-2 weeks):** Run both paths in parallel with read verification. Your application reads from both the old and new locations, compares results, and logs discrepancies. Fix any data transformation bugs.

- **Phase 4 (1 day):** Cut over. During a maintenance window (or using feature flags for zero-downtime), switch the migrated tenants to their new databases. Keep the shared database as a fallback for 2 weeks.

Total timeline: 6-12 weeks per batch of tenants. Budget $30,000-80,000 in engineering time for a mid-complexity SaaS product. Tools like AWS Database Migration Service ($0.018/hour per replication instance) and pgloader (free, open source) reduce manual work.

### Migrating from Database Per Tenant to Shared Schema

Less common but it happens, usually when operational costs spiral. The process is similar but reversed: merge schemas, reconcile ID conflicts (auto-incrementing IDs will collide), and add tenant_id columns to every table. Budget 8-16 weeks and plan for extensive data validation. Using UUIDs as primary keys from day one avoids the worst of the collision problem.

### The Best Strategy: Build an Abstraction Layer Early

If you are uncertain which model you will need long-term, build a thin data access layer that abstracts the tenancy model. Every database call goes through a TenantContext that resolves the correct connection or filter. This adds maybe 2-3 days of upfront work but makes future migration 10x easier. Your [database scaling strategy](/blog/how-to-scale-a-database) should account for this from the beginning.

## Decision Framework: Which Model Fits Your SaaS

After building dozens of these systems, we have distilled the decision into a framework that works for 90% of SaaS products. Answer these five questions honestly.

### 1. How Many Tenants Will You Have in 2 Years?

Under 100 tenants: database per tenant is operationally feasible. 100-5,000 tenants: shared schema or hybrid (schema per tenant) is strongly preferred. Over 5,000 tenants: shared schema is almost always the right call. Managing thousands of databases is a full-time job. You will need a dedicated platform engineer.

### 2. What Is Your Average Contract Value?

Under $100/month per tenant: shared schema. You cannot afford the per-tenant infrastructure cost. $100-1,000/month: shared schema with optional isolation for premium tiers. Over $1,000/month: database per tenant becomes financially viable and may be a competitive advantage ("your data is completely isolated" is a selling point in enterprise sales).

### 3. Do Your Customers Require Compliance Certifications?

If you are selling to healthcare, finance, or government, data isolation is often a hard requirement. SOC 2 Type II auditors will scrutinize your tenant isolation model. HIPAA covered entities may require physical data separation. FedRAMP authorization at the moderate or high level effectively mandates per-tenant isolation. If compliance is a core part of your go-to-market, invest in isolation early.

### 4. Do You Need Data Residency Support?

GDPR (EU), PIPEDA (Canada), LGPD (Brazil), and similar regulations may require customer data to reside in specific geographic regions. Shared schema on a single database instance cannot satisfy this without regional sharding. Database per tenant lets you place each customer's data wherever their compliance requirements dictate.

### 5. How Uneven Is Your Tenant Usage Distribution?

If your top 5% of tenants generate 80% of your database load (common in B2B SaaS), the noisy neighbor problem is real. Shared schema with connection pooling limits helps, but database per tenant with right-sized instances is the cleaner solution. PostgreSQL's pg_stat_statements extension helps you identify which tenants consume the most resources before you commit.

![Development team planning SaaS database architecture and multi-tenant strategy on whiteboard](https://images.unsplash.com/photo-1504384308090-c894fdcc538d?w=800&q=80)

## Implementation Checklist: Regardless of Which Model You Pick

Whichever architecture you choose, these practices prevent the most common multi-tenancy disasters:

### Security Fundamentals

- **Never trust application-layer filtering alone.** If you use shared schema, enable PostgreSQL Row Level Security as a second line of defense. A single missing WHERE clause can expose every customer's data.

- **Use separate database credentials per environment.** Your staging database should not share credentials with production. Obvious, but we have seen it.

- **Encrypt data at rest and in transit.** AWS RDS, Supabase, Neon, and PlanetScale all support this by default. Verify it is enabled.

- **Audit tenant data access.** Log which tenant's data is accessed, by whom, and when. This is a SOC 2 requirement and a debugging lifesaver.

### Performance Foundations

- **Index tenant_id columns.** In shared schema, every table should have a composite index starting with tenant_id. Without this, your queries do full table scans filtered by tenant. At 1 million rows, that query goes from 2ms to 2 seconds.

- **Use connection pooling.** PgBouncer (free, open source) or Supabase's built-in pooler prevents connection exhaustion. PostgreSQL defaults to 100 max connections. With 500 tenants hitting your API, you will exhaust that in seconds without pooling.

- **Monitor per-tenant query performance.** Use pg_stat_statements grouped by tenant to identify expensive queries before they affect other customers.

- **Plan your [database technology choice](/blog/postgresql-vs-mongodb) around your query patterns.** PostgreSQL handles 95% of SaaS workloads, but document-heavy applications with unstructured data may benefit from MongoDB or a hybrid approach.

### Operational Readiness

- **Automate tenant provisioning.** Whether it is creating a row in your tenants table or spinning up a new database, it should be a single API call. Manual tenant setup does not scale past 20 customers.

- **Build tenant-aware monitoring.** Your alerting should tell you "Tenant X is experiencing slow queries" not just "the database is slow." Datadog, Grafana, and New Relic all support custom dimensions for this.

- **Test with realistic tenant counts.** Your test environment should have at least 100 simulated tenants with realistic data volumes. Performance at 5 tenants tells you nothing about behavior at 500.

- **Document your tenancy model.** New engineers who do not understand your multi-tenancy model will write bugs that leak data across tenants. Make this part of onboarding.

## Pick a Model, Build the Abstraction, Ship It

Here is the uncomfortable truth: for 80% of early-stage SaaS products, shared schema is the correct choice. It is simpler, cheaper, and faster to build. The remaining 20% need per-tenant isolation because of compliance requirements, enterprise customer demands, or extreme performance isolation needs. Almost nobody regrets starting with shared schema and adding isolation later for the tenants that require it.

The one thing that will save you regardless is a clean data access layer. Do not scatter raw SQL queries with tenant_id filters throughout your codebase. Centralize tenant resolution, use middleware to inject tenant context, and make the tenancy model a configuration concern rather than something baked into every database call. This abstraction costs 2-3 days upfront and saves months if you ever change your approach.

If the multi-tenancy decision is keeping you stuck, stop researching and start building. Pick shared schema with PostgreSQL RLS, build the abstraction layer, and ship. You can migrate later if you need to. The bigger risk is spending weeks on architecture decisions while your competitors ship features.

Need help designing your multi-tenant architecture or migrating between models? We have done this dozens of times across every major cloud provider. [Book a free strategy call](/get-started) and we will map out the right approach for your product, compliance requirements, and growth trajectory.

---

*Originally published on [Kanopy Labs](https://kanopylabs.com/blog/database-per-tenant-vs-shared-schema-multi-tenant-saas)*
