Every SaaS application must isolate customer data while sharing infrastructure efficiently. Django supports three multi-tenancy strategies, each with different trade-offs for data isolation, operational complexity, and per-tenant cost.
1. Shared Database with Row-Level Security (most common)
- All tenants share the same database and the same tables. Every row includes a
tenant_idforeign key. Queries are automatically filtered by tenant using middleware or model managers. - Django packages:
django-multitenant(Citus Data),django-scopes, or custom middleware withthreading.local() - Database setup: Standard PostgreSQL with indexes on
tenant_id. Enable PostgreSQL Row-Level Security (RLS) policies for defence-in-depth:CREATE POLICY tenant_isolation ON app_table USING (tenant_id = current_setting('app.current_tenant')::int); - Pros: Simplest to implement, lowest infrastructure cost (one database for all tenants), easy migrations (one schema), works with Django ORM out of the box
- Cons: Noisy-neighbour risk (one tenant's heavy query affects all), harder to comply with data residency requirements, backup/restore is all-or-nothing
- Best for: B2B SaaS with fewer than 10,000 tenants, SMB-focused products, MVPs. Development cost: EUR 8,000-12,000.
2. Schema-Per-Tenant (PostgreSQL schemas)
- Each tenant gets their own PostgreSQL schema within a single database. The
publicschema holds shared tables (users, plans, billing). Tenant schemas hold application data. - Django package:
django-tenants(the most mature option, 2,800+ GitHub stars). Middleware setssearch_pathper request based on subdomain or header. - Database setup:
CREATE SCHEMA tenant_acme; SET search_path TO tenant_acme, public;Django migrations run per-schema automatically viapython manage.py migrate_schemas. - Pros: Strong data isolation without separate databases, per-tenant backup/restore possible, tenant-specific customisations via schema differences
- Cons: Migration complexity grows with tenant count (1,000 tenants = 1,000 schema migrations), connection pooling requires schema-aware configuration (PgBouncer with
search_pathhooks), max ~5,000 schemas before PostgreSQL catalog performance degrades - Best for: B2B SaaS with 50-5,000 tenants, products requiring data isolation for compliance (GDPR, HIPAA), enterprise customers demanding logical separation. Development cost: EUR 10,000-18,000.
3. Database-Per-Tenant
- Each tenant gets a fully separate PostgreSQL database. Django's database router directs queries to the correct database.
- Django setup: Dynamic
DATABASESconfiguration via custom database router. Usedjango-dynamic-db-routeror implementclass TenantRouterwithdb_for_read()anddb_for_write()methods. - Pros: Complete isolation (compliance-friendly), independent scaling per tenant, easy per-tenant backup/restore/deletion, no noisy-neighbour issues
- Cons: Highest infrastructure cost (separate database per tenant), operational complexity (connection management, monitoring), cross-tenant queries require federation
- Best for: Enterprise SaaS with fewer than 200 large tenants, healthcare/fintech with strict compliance, tenants requiring dedicated resources. Development cost: EUR 15,000-25,000.