Multi-Tenant-SaaS-Architektur: Muster, die 2026 skalieren
Jedes SaaS-Produkt steht irgendwann vor derselben Architekturentscheidung – meistens zum denkbar schlechtesten Zeitpunkt: wenn der erste Enterprise-Kunde fordert, dass seine Daten vollständig von anderen Kunden isoliert werden, oder wenn ein Compliance-Audit zeigt, dass der Shared-Schema-Ansatz mehr preisgibt als er sollte.
Das Multi-Tenancy-Modell, das Sie wählen, bestimmt, ob Ihre Architektur mit Ihrem Unternehmen skalieren kann – und es prägt weit mehr als Ihre Datenbankstruktur. Es beeinflusst Ihre Sicherheitslage, Ihre Fähigkeit zur kundenspezifischen Anpassung, Ihre Preisgestaltungsflexibilität, Ihre operative Komplexität und wie schmerzhaft die nächste Migration sein wird. Eine nachträgliche Entscheidung ist teuer. Teams, die diese Wahl bewusst treffen – bevor sie den ersten zahlenden Kunden onboarden –, verschaffen sich Optionen, die Teams, die die Entscheidung aufschieben, selten haben.
Dieser Beitrag vergleicht die drei kanonischen Multi-Tenancy-Muster, ordnet sie realen Geschäftssituationen zu und geht durch die Implementierungsüberlegungen für PHP/Symfony-Backends mit Next.js-Frontends.
Was Multi-Tenancy wirklich bedeutet
Eine mandantenfähige SaaS-Anwendung bedient mehrere unabhängige Kunden – Mandanten – aus einer einzigen Codebasis und typischerweise einer gemeinsam genutzten Infrastruktur. Mandanten sollten voneinander nichts wissen, nicht auf die Daten des jeweils anderen zugreifen können und das Produkt so erleben, als wäre es exklusiv für sie gebaut worden.
Das Wort „Isolation" ist die Schlüsselvariable über die drei Muster hinweg. Isolation kann auf der Anwendungsschicht erreicht werden (der Code verhindert mandantenübergreifenden Datenzugriff), auf der Schema-Schicht (Mandanten haben separate Datenbankschemas) oder auf der Infrastrukturschicht (Mandanten haben separate Datenbankinstanzen). Jede Isolationsebene hat ein anderes Kostenprofil und eine andere Fehlerfläche.
Die drei Muster
Shared Schema (Zeilenbasierte Isolation)
Im Shared-Schema-Muster teilen alle Mandanten dieselben Datenbanktabellen. Jede mandantenspezifische Tabelle enthält eine tenant_id-Spalte, und jede Abfrage wird nach dieser Spalte gefiltert. Eine users-Tabelle enthält Benutzer aller Mandanten; die Anwendung filtert bei jedem Lese- und Schreibvorgang nach tenant_id.
// Symfony: Doctrine-Abfrage immer auf aktuellen Mandanten begrenzt
$users = $this->em->getRepository(User::class)->findBy([
'tenantId' => $this->tenantContext->getId(),
'status' => 'active',
]);
Dieses Muster ist am günstigsten zu bauen und zu betreiben. Sie haben eine Datenbank, ein Schema, einen Satz Migrationen. Einen neuen Mandanten hinzuzufügen ist ein einzelnes INSERT in eine tenants-Tabelle.
Die Kosten liegen darin, dass Isolation vollständig in der Anwendungsschicht liegt. Ein einziger fehlender tenant_id-Filter in einer Abfrage – ein Entwickler, der eine einzige WHERE-Klausel vergisst – gibt Daten mandantenübergreifend preis. Das ist nicht hypothetisch; es ist die häufigste Ursache für Mandanten-Datenlecks in produktiven SaaS-Anwendungen.
In Symfony ist die Standardmaßnahme ein Doctrine-Filter, der bei jeder Abfrage für mandantenspezifische Entities automatisch WHERE tenant_id = :current_tenant anhängt:
// src/Doctrine/TenantFilter.php
class TenantFilter extends SQLFilter
{
public function addFilterConstraint(ClassMetadata $targetEntity, string $targetTableAlias): string
{
if (!$targetEntity->hasField('tenantId')) {
return '';
}
return $targetTableAlias . '.tenant_id = ' . $this->getParameter('tenantId');
}
}
Das eliminiert die Fehlerklasse „vergessene WHERE-Klausel", erfordert aber Disziplin zur korrekten Aktivierung und kann bei komplexen JOIN-Abfragen und aggregierten Reports subtile Probleme verursachen.
Beste Eignung: Frühphasen-SaaS, KMU-orientierte Produkte, Produkte, bei denen Mandanten ähnliche Datenvolumina haben, und Produkte, bei denen operative Einfachheit wichtiger ist als strenge Isolationsgarantien.
Warnsignale: Jeder Enterprise-Kunde, der fragt „Wo werden unsere Daten gespeichert?", regulierte Branchen wie FinTech oder Healthcare, in denen Compliance-Anforderungen eine Datentrennung vorschreiben, und Produkte, bei denen mandantenspezifische Datenbank-Backups oder Exporte ein Feature sind.
Separate Schemas (Schema-Level-Isolation)
Im Separate-Schema-Muster erhält jeder Mandant sein eigenes Datenbankschema innerhalb eines einzelnen Datenbankservers. In PostgreSQL entspricht das direkt PostgreSQL-Schemas. In MySQL entspricht das separaten Datenbanken auf derselben Serverinstanz. Tabellen sind mandantenübergreifend identisch; nur der Schema-Namespace unterscheidet sich.
// Schema-Kontext pro Request wechseln in Symfony
// doctrine.yaml
// Dynamisch über einen benutzerdefinierten Connection-Wrapper aufgelöst
class TenantConnectionWrapper extends Connection
{
public function connect(): bool
{
$connected = parent::connect();
if ($connected && $this->tenantContext->hasActiveTenant()) {
$schema = 'tenant_' . $this->tenantContext->getId();
$this->executeStatement('SET search_path TO ' . $schema . ', public');
}
return $connected;
}
}
Dieses Muster bietet stärkere Isolation als Shared Schema. Eine Abfrage, die die Mandanten-Begrenzung vergisst, gibt ein leeres Ergebnis zurück statt die Daten eines anderen Mandanten, weil sie buchstäblich im falschen Schema sucht. Mandantenübergreifende Datenlecks erfordern einen expliziten Schemanamen in einer Abfrage – ein offensichtlicherer Fehler, den Code-Reviews tendenziell erkennen.
Operativ ist dieses Muster deutlich teurer als Shared Schema. Migrationen auszuführen bedeutet, sie einmal pro Mandanten-Schema auszuführen. Ein Produkt mit 500 Mandanten führt jede Migration 500-mal aus. Schema-Drift – bei dem einige Mandanten eine Migration ausgeführt haben und andere nicht – wird ein echtes operatives Risiko, das Werkzeuge zur Verwaltung erfordert.
Die Daten-Isolationsgeschichte ist überzeugend für Mid-Market- und Enterprise-Kunden. Die Daten jedes Mandanten können unabhängig exportiert, gesichert oder wiederhergestellt werden. Mandantenspezifisches Performance-Tuning (zusätzliche Indizes für einen Hochvolumen-Mandanten) ist möglich, ohne andere zu beeinträchtigen.
Beste Eignung: Mid-Market-SaaS-Produkte, Produkte für Kunden in regulierten Branchen, bei denen Schema-Level-Isolation Compliance-Anforderungen erfüllt, und Produkte, bei denen mandantenspezifische Datenbankoperationen (Backup, Export, Restore) Teil des Angebots sind.
Warnsignale: Produkte mit Hunderten oder Tausenden von Mandanten (Migrationsverwaltung wird aufwändig), und Teams ohne dedizierte DevOps-Kapazität zur Verwaltung von Schema-Lifecycle-Werkzeugen.
Separate Datenbanken (Datenbank-Level-Isolation)
Das isolierteste Muster: Jeder Mandant erhält eine eigene Datenbankinstanz, möglicherweise auf dedizierter Infrastruktur. Es gibt keinen gemeinsamen Server zwischen Mandanten.
Dieser Ansatz ist operativ mit Abstand am teuersten. Jeder neue Mandant erfordert das Bereitstellen einer Datenbankinstanz, das Ausführen von Migrationen auf einem neuen Schema, die Konfiguration von Verbindungsparametern und die Verwaltung von Connection-Pooling auf Mandantenebene. In der Cloud bedeutet das typischerweise eine separate RDS- oder Cloud-SQL-Instanz pro Enterprise-Kunden mit den damit verbundenen Pro-Instanz-Kosten.
Für die meisten SaaS-Produkte sind separate Datenbanken nur für eine kleine Anzahl von Enterprise-Kunden mit strengen vertraglichen Isolationsanforderungen gerechtfertigt – Kunden, die genug zahlen, um den operativen Overhead zu finanzieren. Einige Produkte implementieren ein Hybridmodell: KMU- und Mid-Market-Mandanten auf Shared Schema oder separaten Schemas, mit einem „Dedicated Instance"-Tier für Enterprise-Accounts, die bereit sind, einen Aufpreis zu zahlen.
// Dynamische Connection-Auflösung nach Mandanten-Identifier
class TenantConnectionFactory
{
public function getConnection(string $tenantId): Connection
{
$config = $this->tenantRepository->getConnectionConfig($tenantId);
// Config enthält Host, Port, DB-Name, Credentials aus dem Secrets Manager
return DriverManager::getConnection($config);
}
}
Beste Eignung: Enterprise-fokussiertes SaaS mit vertraglichen Datenisolationsanforderungen, Produkte in stark regulierten Branchen (Banking, Healthcare, Government) und Produkte mit einer kleinen Anzahl großer, hochwertiger Mandanten.
Warnsignale: Produkte mit Self-Service-Pricing, hoher Mandanten-Fluktuation oder mehr als einer Handvoll Kunden in diesem Tier.
Das richtige Muster wählen: Ein Entscheidungsrahmen
Die Wahl zwischen diesen Mustern ist primär keine technische Entscheidung – sie ist eine Geschäftsentscheidung mit technischen Konsequenzen.
Beginnen Sie mit Ihrem Zielkunden. Wenn Ihr primärer Käufer ein KMU-Entscheider ist, der sich per Kreditkarte anmeldet, ist Shared Schema fast sicher der richtige Ausgangspunkt. Die operative Einfachheit multipliziert sich über die Zeit, und die Sicherheitsrisiken sind mit diszipliniertem Anwendungsschicht-Filtering handhabbar.
Wenn Ihr erster Enterprise-Deal erfordert, dass Sie auf die Frage „Sind unsere Daten physisch von anderen Kunden getrennt?" mit „Ja" antworten, brauchen Sie mindestens separate Schemas. Das nachträgliche Einbauen nach dem Bauen auf Shared Schema ist ein erhebliches Migrationsprojekt – nicht unmöglich, aber teuer und riskant.
Bedenken Sie Compliance-Anforderungen frühzeitig. FinTech-Produkte unter PSD2, Healthcare-Produkte mit HIPAA-Verpflichtungen und alle Produkte, die EU-personenbezogene Daten unter DSGVO-mit-Enterprise-DPA-Anforderungen speichern, sehen sich oft vertraglichen Verpflichtungen gegenüber, die Shared Schema nicht erfüllen kann. Ein Tech-Stack-Strategie-Engagement vor dem Bauen ist erheblich günstiger als das nachträgliche Einrüsten von Isolation.
Schließlich berücksichtigen Sie Ihren Migrationspfad. Teams, die mit Shared Schema beginnen und später separate Schemas benötigen, sehen eine vorhersehbare Migration: Mandantenspezifische Schemas hinzufügen, Zeilen in Mandanten-Schemas verschieben, Connection-Routing aktualisieren, Shadow-Traffic ausführen, umschalten. Das ist machbar. Teams, die mit separaten Datenbanken beginnen und aus Kostengründen konsolidieren müssen, haben ein schwierigeres Problem. Einfacher anfangen und hochskalieren ist im Allgemeinen eine bessere Progression als komplex anfangen und versuchen zu vereinfachen.
Mandanten-Isolation in der Praxis: Was schiefläuft
Unabhängig vom gewählten Muster kommen die häufigsten Fehler in Multi-Tenant-Systemen aus denselben Quellen.
Hintergrundjobs, die den Mandanten-Kontext ignorieren. Ein Job, der einen wöchentlichen Zusammenfassungsbericht generiert, muss wissen, welche Mandantendaten zusammengefasst werden sollen. Ohne explizite Mandanten-Bindung verarbeiten Jobs entweder die Daten aller Mandanten zusammen oder schlagen lautlos fehl. In Symfony Messenger bedeutet das, den Mandanten-Identifier als Teil der Message-Payload zu übergeben und den Mandanten-Kontext im Message-Handler vor jedem Datenzugriff zu setzen.
Dateispeicher ohne Mandanten-Namespacing. Hochgeladene Dateien in einem flachen S3-Bucket mit sequenziellen IDs werden irgendwann dem falschen Mandanten bereitgestellt, wenn der Speicherschlüssel erratbar ist. Stellen Sie jedem Speicherschlüssel den Mandanten-Identifier voran und bereitgestellen Sie Dateien über eine signierte URL oder einen autorisierungsprüfenden Proxy – niemals direkt aus einem öffentlich zugänglichen Bucket-Pfad.
Reporting-Abfragen, die mandantenübergreifend aggregieren. Interne Analytics-Abfragen – aktive Benutzer insgesamt, Umsatz nach Plan, Feature-Adoption – laufen absichtlich über alle Mandanten. Diese Abfragen dürfen niemals Daten in mandantenorientierten UIs sichtbar machen. Das Beibehalten einer strikten Unterscheidung zwischen internen (mandantenübergreifenden) und externen (mandantenbegrenzten) Datenzugriffspfaden verhindert versehentliche Datenlecks durch falsch begrenzte Reports.
Caching ohne mandantenbezogene Schlüssel. Ein Redis-Cache, der user:123:profile ohne Mandanten-Präfix speichert, wird User 123s Profil an jeden Mandanten bereitstellen, der diese User-ID anfragt. Jeder Cache-Schlüssel in einer Multi-Tenant-Anwendung sollte den Mandanten-Identifier enthalten: tenant:{tenantId}:user:{userId}:profile.
Ein Code-Quality-Audit einer Multi-Tenant-Anwendung prüft speziell auf jedes dieser Muster – sie erscheinen häufig genug, dass sie eine vorhersehbare Fehlerklasse darstellen, keine Einzelfehler.
Next.js-Frontend-Überlegungen
Im Frontend manifestiert sich Multi-Tenancy primär als Routing und Konfiguration. Zwei gängige Ansätze:
Subdomain-basiertes Routing (acme.yourapp.com, globex.yourapp.com) ist die sauberere Enterprise-Erfahrung. In Next.js mit dem App Router behandelt Middleware die Subdomain-Extraktion und gibt den Mandanten-Kontext an den Request weiter:
// middleware.ts
export function middleware(request: NextRequest) {
const hostname = request.headers.get('host') || '';
const subdomain = hostname.split('.')[0];
const response = NextResponse.next();
response.headers.set('x-tenant-id', subdomain);
return response;
}
Pfadbasiertes Routing (yourapp.com/acme/dashboard) ist einfacher zu deployen, legt den Mandanten-Identifier aber in jede URL offen, was manche Enterprise-Kunden ablehnen. Es funktioniert gut für Produkte, bei denen der Mandanten-Identifier nicht sensibel ist.
Welchen Ansatz Sie auch wählen: Der Mandanten-Identifier sollte serverseitig aufgelöst und bei jedem Request gegen Ihre Mandanten-Registry validiert werden – niemals aus vom Client bereitgestellten Headern oder Query-Parametern vertraut werden.
Die Migration, die Sie vermeiden wollen
Die teuerste Multi-Tenancy-Arbeit passiert, wenn ein Produkt auf Shared Schema gewachsen ist und ein neuer Enterprise-Kunde separate Schema-Isolation fordert. Die Migration beinhaltet das Extrahieren der Zeilen jedes Mandanten in mandantenspezifische Schemas, während die Anwendung läuft, die Wahrung der referenziellen Integrität und die Sicherstellung, dass während des Übergangs keine Daten doppelt geschrieben oder verloren gehen.
Diese Migration ist machbar, erfordert aber typischerweise zwei bis vier Wochen Senior-Engineering-Zeit, eine sorgfältig choreografierte Deployment-Sequenz und einen Rollback-Plan. Teams, die ihr Tenancy-Modell vor dem Bauen planen, vermeiden diese Kosten vollständig.
Wenn Sie Multi-Tenancy-Modelle für ein Produkt evaluieren, das Sie gerade bauen, ist die Zeitinvestition für die richtige Entscheidung in Tagen gemessen. Sie falsch zu treffen ist in Wochen Migrationsarbeit pro Enterprise-Kunden gemessen, der ein höheres Isolationsniveau fordert.
Fazit
Multi-Tenant-SaaS-Architektur ist eine der wenigen frühen technischen Entscheidungen mit sich multiplizierenden geschäftlichen Konsequenzen. Shared Schema gibt Ihnen operative Einfachheit und erzwingt Disziplin auf Anwendungsschicht. Separate Schemas geben Ihnen bedeutungsvolle Isolation mit überschaubarem operativen Overhead. Separate Datenbanken geben Ihnen Enterprise-Garantien mit proportionalen Kosten.
Die richtige Antwort hängt davon ab, wer Ihre Kunden sind, in welchen Compliance-Umgebungen sie tätig sind und wie Sie Ihr Produkt bepreisen. Diese Entscheidung vor dem Bauen richtig zu treffen – statt sie nach einem Enterprise-Deal nachzurüsten, der es einfordert – ist eine der hebel-stärksten technischen Entscheidungen, die Sie treffen werden.
Wolf-Tech hat zahlreichen SaaS-Teams dabei geholfen, Multi-Tenant-Architekturen über alle drei Muster hinweg zu entwerfen und zu implementieren, einschließlich Migrationen von Shared-zu-Schema-separierten Modellen. Wenn Sie diese Entscheidung jetzt treffen oder ein System geerbt haben, das weiterentwickelt werden muss, bieten wir eine kostenlose Erstberatung an. Kontaktieren Sie uns unter hello@wolf-tech.io oder besuchen Sie wolf-tech.io, um Ihre Architektur zu besprechen.

