Multitenancy Background
dns Software Architecture Patterns

What is Multitenancy?

Multitenancy is an architecture where a single instance of software serves multiple customers (tenants). It is the backbone of almost every modern SaaS application, balancing resource efficiency with data isolation.

The Apartment Analogy

To understand multitenancy, compare buying a house vs. renting an apartment.

Single Tenant Houses
home

Single Tenancy

Like owning a detached house. You have your own walls, plumbing, and security system.

  • ✓ Total isolation & control
  • ✓ No noisy neighbors
  • ✗ Expensive to build & maintain
  • ✗ Hard to upgrade (visit every house)
SaaS Standard
Multi Tenant Apartment
apartment

Multi-Tenancy

Like an apartment complex. Everyone shares the foundation, plumbing, and security guard, but has their own private key.

  • ✓ Cost efficient (shared resources)
  • ✓ Easy updates (fix the roof once)
  • ! Requires strict security rules
  • ! "Noisy neighbor" risk

Database Strategies

How do we actually separate the data? There are three main patterns.

database Database per Tenant (Silo)

The "Premium" option. Each tenant gets their completely own database instance. The application connects to a different DB based on who is logging in.

Pros

  • Ultimate data isolation (physical separation).
  • Can restore one tenant's backup without affecting others.
  • No "noisy neighbor" effect on IOPS.

Cons

  • Expensive (infrastructure costs multiply).
  • Hard to manage (1,000 tenants = 1,000 DBs to migrate).
  • Resource wasteful for small tenants.
Pseudocode Logic

const tenant = getTenant(request);

const connection = createConnection({

host: 'db-cluster-1',

database: `db_${tenant.id}` // distinct DB

});

Silo Architecture Diagram

Request Simulator

See how the backend handles a request for "All Orders" depending on the strategy and the logged-in user.

server_logs.log
> Waiting for request...
Best Practice 2025

The Solution: Row Level Security (RLS)

The biggest fear with the "Shared Database" model is developer error—forgetting the `WHERE` clause. PostgreSQL RLS solves this by enforcing the rule at the database engine level.

Even if your backend code tries to `SELECT * FROM users`, the database itself intercepts the query and says, "Wait, you are Tenant A, so you only see Tenant A's rows."

Read Postgres Docs open_in_new
init.sql
-- 1. Enable Security on Table
ALTER TABLE orders ENABLE ROW LEVEL SECURITY;

-- 2. Create Policy
CREATE POLICY tenant_isolation_policy ON orders
USING (tenant_id = current_setting('app.current_tenant'));

-- 3. App code just sets the variable
SET app.current_tenant = 'tenant_a';
SELECT * FROM orders; 
-- ^ Safe! Returns only tenant_a orders automatically.

Summary Comparison

Feature Database per Tenant Schema per Tenant Shared DB (Pool)
Isolation Level Highest (Physical) Medium (Logical) Lowest (Logical)
Cost efficiency Low ($$$) Medium ($$) High ($)
Schema Migrations Hard (Run 1000x) Hard (Run 1000x) Easy (Run 1x)
Best Use Case Banking, Healthcare, Enterprise Mid-market B2B High-volume SaaS (Slack, Notion)
Complexity Infrastructure Heavy Scripting Heavy App Logic / Security Heavy