In a multi - tenant application, it is crucial to identify the tenant for each request. This can be done through various means such as subdomains, custom headers, or URL paths.
Software - as - a - Service (SaaS) applications are a prime example of multi - tenant systems. A single SaaS application can serve multiple businesses, each with its own set of users, data, and configurations. For example, a project management SaaS can have different projects and teams for each tenant.
Hosting platforms that offer web hosting services to multiple clients can use multi - tenant architecture. Each client can have its own website with isolated data and settings.
Here is a simple example of implementing the shared database, shared schema approach in Django.
# models.py
from django.db import models
from django.conf import settings
class Tenant(models.Model):
name = models.CharField(max_length=100)
# Other tenant - specific fields
class TenantAwareModel(models.Model):
tenant = models.ForeignKey(Tenant, on_delete=models.CASCADE)
class Meta:
abstract = True
class Product(TenantAwareModel):
name = models.CharField(max_length=100)
price = models.DecimalField(max_digits=10, decimal_places=2)
# middleware.py
class TenantMiddleware:
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
# Assume tenant ID is passed in the subdomain
subdomain = request.get_host().split('.')[0]
try:
tenant = Tenant.objects.get(name=subdomain)
request.tenant = tenant
except Tenant.DoesNotExist:
# Handle the case where the tenant is not found
request.tenant = None
response = self.get_response(request)
return response
# settings.py
MIDDLEWARE = [
#...
'your_app.middleware.TenantMiddleware',
#...
]
In views, you can filter the data based on the tenant:
# views.py
from django.shortcuts import render
from .models import Product
def product_list(request):
products = Product.objects.filter(tenant=request.tenant)
return render(request, 'product_list.html', {'products': products})
To implement the shared database, separate schemas approach, you can use the django - tenants
library.
First, install the library:
pip install django - tenants
# settings.py
DATABASE_ROUTERS = (
'django_tenants.routers.TenantSyncRouter',
)
# models.py
from django.db import models
from django_tenants.models import TenantMixin, DomainMixin
class Client(TenantMixin):
name = models.CharField(max_length=100)
paid_until = models.DateField()
class Domain(DomainMixin):
pass
# urls.py (tenant - specific)
from django.urls import path
from .views import tenant_view
urlpatterns = [
path('', tenant_view, name='tenant_view'),
]
# urls.py (public)
from django.urls import path, include
from django_tenants.views import TenantRedirectView
urlpatterns = [
path('', TenantRedirectView.as_view(), name='tenant_redirect'),
path('public/', include('public_app.urls')),
]
In a shared database, shared schema approach, improper handling of tenant identifiers can lead to data leakage between tenants. For example, if the tenant identifier is not correctly applied in queries, one tenant may access another tenant’s data.
As the number of tenants grows, especially in a shared database environment, performance can degrade. Large tables with data from multiple tenants can slow down queries.
In a shared database, separate schemas approach, managing schema changes across multiple schemas can be challenging. Updating the schema for one tenant may affect others if not done carefully.
Using middleware to identify the tenant for each request ensures that the tenant context is available throughout the request lifecycle.
Thoroughly test the multi - tenant application, especially for data isolation and performance. Use unit tests, integration tests, and load tests to catch issues early.
Monitor the performance of the application as the number of tenants grows. Use tools like Django Debug Toolbar and database monitoring tools to identify and address performance bottlenecks.
Multi - tenant architecture in Django offers a powerful way to build scalable and cost - effective applications that can serve multiple tenants. By understanding the core concepts, typical usage scenarios, common pitfalls, and best practices, developers can implement multi - tenant systems that are secure, performant, and easy to maintain. Whether it’s a SaaS application or a hosting platform, Django provides the flexibility to choose the right multi - tenant approach for the project.