Skip to main content

Multi-Tenancy

Multi-tenancy is a software architecture where a single instance of an application serves multiple customers (tenants), with each tenant's data isolated from others. It's fundamental to SaaS (Software as a Service) applications.

Tenancy Models

Single-Tenant

One instance per customer:

Customer A → App Instance A → Database A
Customer B → App Instance B → Database B

Multi-Tenant

One instance serves all customers:

Customer A ─┐
Customer B ─┼→ Shared App Instance → Shared Database (with isolation)
Customer C ─┘

Data Isolation Strategies

1. Separate Databases

Each tenant has their own database:

ProsCons
Strongest isolationHigher infrastructure cost
Easy backup/restore per tenantMore complex deployment
Tenant-specific customisationConnection pool management

2. Separate Schemas

One database, separate schemas per tenant:

-- PostgreSQL
CREATE SCHEMA tenant_a;
CREATE SCHEMA tenant_b;

SELECT * FROM tenant_a.users;

3. Shared Tables with Tenant ID

All tenants in same tables, filtered by ID:

CREATE TABLE users (
id INT PRIMARY KEY,
tenant_id INT NOT NULL,
name VARCHAR(255),
-- ...
);

-- All queries filtered
SELECT * FROM users WHERE tenant_id = 123;

Implementation Patterns

Middleware Tenant Resolution

const tenantMiddleware = async (req, res, next) => {
// From subdomain: tenant.example.com
const subdomain = req.hostname.split('.')[0];

// Or from header
const tenantId = req.headers['x-tenant-id'];

req.tenant = await getTenant(subdomain || tenantId);
next();
};

Query Scoping

// Automatically scope all queries
const getUsersForTenant = (tenantId) => {
return db.query('SELECT * FROM users WHERE tenant_id = $1', [tenantId]);
};

What We Like

  • Cost efficiency: Shared infrastructure reduces costs
  • Simpler operations: One deployment, one codebase
  • Faster onboarding: New tenants without new infrastructure
  • Feature rollouts: Easier to update all tenants

What We Don't Like

  • Complexity: Isolation logic pervades the codebase
  • Noisy neighbors: One tenant can impact others
  • Compliance challenges: Some industries require true isolation
  • Schema changes: Must consider all tenants

Security Considerations

  1. Never trust client-provided tenant ID: Resolve from authenticated session
  2. Enforce at database level: Row-level security (RLS) when possible
  3. Audit access patterns: Log cross-tenant access attempts
  4. Test isolation: Verify queries can't leak data

Best Practices

  1. Choose isolation level carefully: Based on compliance and scale needs
  2. Implement RLS: PostgreSQL Row-Level Security provides defense in depth
  3. Centralize tenant resolution: One place, not scattered throughout code
  4. Plan for migration: Tenants may need stronger isolation later
  5. Monitor per-tenant: Identify resource-heavy tenants