Entwicklung von Multi-Tenant-SaaS: Eine Datenbank pro Mandant vs. gemeinsames Schema
Die wichtigste architektonische Entscheidung bei der SaaS-Entwicklung: Wie lassen sich Mandantendaten isolieren? Wir vergleichen drei Ansätze anhand einer realistischen Kostenanalyse, Migrationsstrategien und Code-Beispielen.
Die Entscheidung, die alles bestimmt
Bei der Entwicklung eines SaaS-Produkts ist die wichtigste architektonische Entscheidung die Isolierung der Mandanten. Wer hier einen Fehler macht, wird später Monate mit der Migration verbringen. Es gibt drei Ansätze, die jeweils klare Vor- und Nachteile mit sich bringen:
Ansatz 1: Gemeinsame Datenbank, gemeinsames Schema (Isolation auf Zeilenebene)
Die Daten aller Mandanten werden in denselben Tabellen gespeichert und durch die Spalte „tenant_id“ voneinander unterschieden. Dies ist der einfachste und kostengünstigste Ansatz.
# Django: Automatische Mandantenfilterung mit Middleware
class TenantMiddleware:
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
# Mandanten aus JWT oder Subdomain
ermitteln request.tenant = get_tenant_from_request(request)
return self.get_response(request)
class TenantManager(models.Manager):
def get_queryset(self):
from threading import local
_thread_locals = local()
tenant = getattr(_thread_locals, 'tenant', None)
qs = super().get_queryset()
if tenant:
qs = qs.filter(tenant_id=tenant.id)
return
qsclass Order(models.Model):
tenant = models.ForeignKey('Tenant', on_delete=models.CASCADE)
# ... weitere Felder
objects = TenantManager() # Alle Abfragen werden automatisch gefiltertVorteile: Einfach, kostengünstig (50–200 $/Monat für eine Datenbank), einfache Bereitstellung, gemeinsamer Verbindungspool. Nachteile: Risiko von Datenlecks, wenn ein Filter vergessen wird, „Noisy-Neighbor“-Problem (die ressourcenintensiven Abfragen eines Mandanten beeinträchtigen andere), erschwerte Einhaltung von Vorschriften (Löschung von Daten gemäß DSGVO).
Ansatz 2: Gemeinsame Datenbank, separate Schemata (PostgreSQL-Schemata)
Jeder Mandant erhält sein eigenes PostgreSQL-Schema innerhalb einer einzigen Datenbank. Die Tabellen sind identisch, jedoch durch Namensräume voneinander getrennt.
# Verwendung der Bibliothek
„django-tenants“# Jede Anfrage legt das Schema basierend auf der
Subdomain fest# settings.
pyDATABASE_ROUTERS = ['django_tenants.routers.TenantSyncRouter']
# Middleware legt das Schema pro Anfrage
fest# acme.yourapp.com -> Schema
„acme“# globex.yourapp.com -> Schema
„globex“# SQL-Äquivalent:
# SET search_path TO 'acme'; -- alle Abfragen greifen nun auf die Tabellen von
acme zu# SELECT * FROM orders; -- gibt nur die Bestellungen von acme zurückVorteile: Starke Isolierung ohne zusätzliche Datenbanken, einfache Datenlöschung (DROP SCHEMA CASCADE), separate Indizes pro Mandant. Nachteile: Komplexe Migration (jedes Schema muss migriert werden), Connection-Pooling ist schwieriger, maximal ~500 Mandanten, bevor die Leistung nachlässt.
Ansatz 3: Eine Datenbank pro Mandant
Jeder Mandant erhält eine eigene Datenbank. Maximale Isolation, maximale Komplexität im Betrieb.
Vorteile: Vollständige Isolierung, unabhängige Skalierung, einfache Einhaltung von Compliance-Anforderungen, Möglichkeit, Unternehmenskunden eine dedizierte Infrastruktur anzubieten. Nachteile: Teuer (50–200 $ pro Mandant und Monat), Alptraum beim Connection-Pooling, Migrationen über Hunderte von Datenbanken hinweg, mandantenübergreifende Analysen erfordern ein Data Warehouse.
Entscheidungsmatrix: Welchen Ansatz soll man wählen?
| Faktor | Gemeinsames Schema | Separate Schemata | Separate Datenbanken |
|---|---|---|---|
| Monatliche Kosten (100 Mieter) | 100–200 Dollar | 200–500 Dollar | 5.000–20.000 $ |
| Obergrenze fĂĽr die Anzahl der Mieter | Unbegrenzt | ~500 | ~100 (ĂĽberschaubar) |
| Datenisolierung | Schwach (auf Zeilenebene) | Stark (auf Schemaebene) | Fertig |
| Compliance (DSGVO/SOC 2) | Schwierig | Mäßig | Einfach |
| Risiko durch laute Nachbarn | Hoch | Mittel | Keine |
| Am besten geeignet für | B2C, SaaS für kleine und mittlere Unternehmen | SaaS für mittelständische Unternehmen | SaaS für Unternehmen |
Unsere Empfehlung: Mit „Shared“ beginnen, dann auf eine höhere Stufe umsteigen
Beginnen Sie mit einem gemeinsamen Schema und Isolation auf Zeilenebene. So kommen Sie schnell auf den Markt und decken 90 % der Anwendungsfälle ab. Wenn Sie Unternehmenskunden gewinnen, die Isolationsgarantien benötigen, bieten Sie separate Schemata oder Datenbanken als Premium-Variante an.
Der Schlüssel liegt darin, Ihre Modelle von Anfang an mit einer `tenant_id` zu entwerfen. Dadurch ist später ein Wechsel zu jedem beliebigen Ansatz möglich, ohne dass Sie Ihre Anwendung neu schreiben müssen.
Die beste Multi-Tenant-Architektur ist die, die zu Ihrer aktuellen Entwicklungsphase passt. Ein Start-up mit 10 Mandanten, das eine separate Datenbank pro Mandant nutzt, zahlt das Zehnfache dessen, was es eigentlich sollte.
— alokknight Engineering
