Multi-Tenant Architecture
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
| โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Tenant Resolution โ
โ (Subdomain, Header, Token โ Tenant Context) โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ
โผ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Application Layer โ
โ (All queries scoped to tenant) โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ
โโโโโโโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโโโโโ
โ โ โ
โผ โผ โผ
โโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโ
โ Tenant A โ โ Tenant B โ โ Tenant C โ
โ (Data) โ โ (Data) โ โ (Data) โ
โโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโ
|
Tenant Model Implementation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
| from django.db import models
from django.conf import settings
class Tenant(models.Model):
name = models.CharField(max_length=255)
subdomain = models.CharField(max_length=63, unique=True)
custom_domain = models.CharField(max_length=255, null=True)
# Billing
stripe_customer_id = models.CharField(max_length=255)
plan = models.ForeignKey('Plan', on_delete=models.PROTECT)
# Configuration
config = models.JSONField(default=dict)
branding = models.JSONField(default=dict) # Logo, colors, etc.
# Compliance (e.g., state-specific rules)
compliance_config = models.JSONField(default=dict)
created_at = models.DateTimeField(auto_now_add=True)
class TenantAwareModel(models.Model):
"""Base class for all tenant-scoped models"""
tenant = models.ForeignKey(
Tenant,
on_delete=models.CASCADE,
db_index=True
)
class Meta:
abstract = True
def save(self, *args, **kwargs):
if not self.tenant_id:
self.tenant = get_current_tenant()
super().save(*args, **kwargs)
class Order(TenantAwareModel):
"""Example: Orders are tenant-scoped"""
product = models.CharField(max_length=255)
amount = models.DecimalField(max_digits=10, decimal_places=2)
objects = TenantManager() # Auto-filters by tenant
|
Tenant Isolation Patterns
| Layer | Isolation Method | Implementation |
|---|
| Database | Row-level filtering | tenant_id column + auto-scope |
| Application | Context middleware | Thread-local/context var |
| API | Token/subdomain | Tenant resolution middleware |
| Background Jobs | Job metadata | Tenant ID in job payload |
| Cache | Key prefixing | tenant:{id}:key pattern |
| Files | Path prefixing | s3://bucket/{tenant_id}/ |
Enterprise Features
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
| class TenantConfiguration:
"""Per-tenant customization"""
def get_branding(self, tenant: Tenant) -> Branding:
return Branding(
logo_url=tenant.branding.get('logo'),
primary_color=tenant.branding.get('primary_color', '#000'),
custom_css=tenant.branding.get('custom_css')
)
def get_compliance_rules(self, tenant: Tenant) -> ComplianceRules:
# e.g., State-specific rules for cannabis delivery
return ComplianceRules(
max_order_weight=tenant.compliance_config.get('max_weight'),
delivery_hours=tenant.compliance_config.get('hours'),
age_verification=tenant.compliance_config.get('age_check', True)
)
def get_sso_config(self, tenant: Tenant) -> Optional[SSOConfig]:
if not tenant.config.get('sso_enabled'):
return None
return SSOConfig(
provider=tenant.config['sso_provider'],
metadata_url=tenant.config['sso_metadata_url']
)
|
Frequently Asked Questions
What is multi-tenant architecture?
Multi-tenant architecture allows multiple customers (tenants) to share the same application instance while keeping their data isolated. It’s essential for SaaS applications, enabling efficient resource utilization and simplified operations.
How much does multi-tenant implementation cost?
Multi-tenant development typically costs $120-170 per hour. Adding multi-tenancy to an existing app starts around $20,000-40,000, while building a new multi-tenant SaaS platform ranges from $75,000-200,000+.
What are the different multi-tenant models?
Three approaches: 1) Shared database with tenant ID column (simplest, lowest isolation), 2) Shared database with separate schemas per tenant (moderate isolation), 3) Separate database per tenant (highest isolation, most complex). I help choose based on your security and scale requirements.
How do you handle tenant data isolation?
I implement: row-level security policies (PostgreSQL RLS), middleware that automatically filters queries, tenant context in all operations, and testing to prevent data leakage. Data isolation is critical, I use defense-in-depth.
Can you add multi-tenancy to an existing application?
Yes, though it requires careful planning. I’ve retrofitted multi-tenancy onto single-tenant apps: adding tenant models, migrating data, implementing filtering, updating tests, and ensuring no cross-tenant data access. It’s a significant undertaking.
Experience:
Case Studies:
Related Technologies: SaaS Development, PostgreSQL, API Security