E-book
23.63
drukowana A5
56.16
Multi-Tenant-SaaS-Architekturen

Bezpłatny fragment - Multi-Tenant-SaaS-Architekturen


Objętość:
142 str.
ISBN:
978-83-8455-876-8
E-book
za 23.63
drukowana A5
za 56.16

Impressum

© Matthias Kreuzberg. Alle Rechte vorbehalten.

Kein Teil dieses Werkes darf ohne vorherige schriftliche Genehmigung des Rechteinhabers reproduziert, in einem Datenverarbeitungssystem gespeichert oder in irgendeiner Form oder mit irgendwelchen Mitteln — elektronisch, mechanisch, durch Fotokopien, Aufnahmen oder auf andere Weise — übertragen werden.

Die in diesem Buch enthaltenen Informationen wurden sorgfältig recherchiert und geprüft. Dennoch übernehmen Autor und Verlag keine Haftung für Schäden, die im Zusammenhang mit der Verwendung dieses Buches entstehen, insbesondere nicht für Schäden, die aus der Anwendung der beschriebenen Architekturmuster in Produktivsystemen entstehen. Jede Umsetzung erfolgt in eigener Verantwortung des Lesers.

Marken- und Produktbezeichnungen (u. a. PostgreSQL, Kubernetes, Redis, AWS, Azure, Google Cloud, OAuth, OpenID Connect) werden ohne Gewährleistung der freien Verwendbarkeit benutzt und sind Eigentum ihrer jeweiligen Rechteinhaber. Die Verwendung dient ausschließlich der Kennzeichnung und impliziert keine Verbindung zu oder Empfehlung durch die jeweiligen Markeninhaber.

Geleitwort

Wer im letzten Jahrzehnt an Unternehmenssoftware gebaut hat, wird die Verschiebung bemerkt haben: Aus der Frage „Wie installieren wir das beim Kunden?” wurde die Frage „Wie halten wir das für tausend Kunden gleichzeitig am Laufen?“. Der Unterschied klingt technisch, ist aber vor allem organisatorisch. Er verändert, wer Verantwortung trägt, wann Fehler sichtbar werden und was ein Release eigentlich bedeutet.

Software-as-a-Service ist längst mehr als ein Vertriebskanal. Sie ist ein eigenes Ingenieurshandwerk, mit spezifischen Fehlerbildern, eigenen Skalierungsgrenzen und einem Anspruch an Betriebsqualität, den frühere Anwendungsgenerationen nie stemmen mussten. Wer sich mit Kubernetes, mit Datenbanken oder mit Identitätssystemen einzeln beschäftigt, findet exzellente Literatur. Wo diese Disziplinen sich im mandantenfähigen Systemdesign kreuzen, wird die Luft dünn.

Der Autor bringt jahrzehntelange Projekterfahrung mit — vom knappen Start-up bis zum regulierten Großkonzern. Diese Erfahrung ist an vielen Stellen spürbar: an der Nüchternheit der Abwägungen, an der Bereitschaft, populäre Empfehlungen zu hinterfragen, und an der Genauigkeit, mit der wirtschaftliche, betriebliche und technische Folgen nebeneinandergestellt werden. Wer dieses Buch aufschlägt, wird nicht mit einer Silberkugel belohnt. Er bekommt etwas Besseres: eine Sammlung ehrlicher Kompromisse.

Ich wünsche allen Leserinnen und Lesern, dass es ihnen so viele produktive Diskussionen ermöglicht, wie mir schon die Durchsicht der frühen Kapitel beschert hat.

Vorwort

Die Idee zu diesem Buch entstand nicht am Schreibtisch, sondern in Meetings. In den Sitzungen, in denen zum wiederholten Mal diskutiert wurde, ob das nächste Modul in einem gemeinsamen Schema aufsetzt oder eine separate Datenbank pro Mandant vorsieht. In den Betriebs-Reviews, in denen ein einziger großer Kunde durch ein ungünstiges Reporting die Latenzen aller anderen Nutzer verdoppelte. In den Post-mortems, in denen ein fehlender Tenant-Kontext dazu geführt hatte, dass Datensätze aus dem falschen Kontext gelesen wurden — ein Vorfall, der sich in einer Zeile Code entscheidet und in Wochen operativer Aufarbeitung endet.

Mandantenfähigkeit ist selten eine akademische Fragestellung. Sie berührt Rechnungsstellung, Betriebskosten, Compliance, Vertrieb und Produktstrategie gleichermaßen. Es reicht deshalb nicht, ein Muster zu kennen. Man muss verstehen, warum es funktioniert, wo seine Grenzen liegen, welche Alternativen wann sinnvoll sind — und, mindestens ebenso wichtig, wann man es lieber sein lässt.

Dieses Buch versucht, dieses Verständnis zu vermitteln. Es beginnt mit Grundlagen, führt durch die typischen Tenancy-Modelle, behandelt Datenisolation, Sicherheit, Skalierung, Performance und Betrieb und schließt mit sechs ausführlichen Fallstudien aus unterschiedlichen Branchen. Jeder Teil steht für sich, doch gemeinsam ergeben sie einen roten Faden: Wie baut man SaaS-Systeme, die man auch nach fünf Jahren noch gerne betreibt?

Ich habe versucht, keine Empfehlung auszusprechen, die ich nicht selbst in Produktion erprobt oder in vergleichbarer Form bei erfahrenen Kollegen gesehen habe. Wo die Branche keine klare Antwort kennt, sage ich das ausdrücklich. Wo eine populäre Praxis meiner Erfahrung nach überschätzt wird, argumentiere ich dagegen. Und wo eine unbequeme Wahrheit ausgesprochen werden muss — etwa dass „vollständige Isolation” oft ein Verkaufsversprechen und selten eine technische Realität ist — tue ich das ebenfalls.

Ich hoffe, dass dieses Buch weniger gelesen als benutzt wird: als Referenz während der Entwurfssitzung, als Argumentationshilfe im Gespräch mit dem Management und als Grundlage für Entscheidungen, die man später nicht bereut.

Für wen dieses Buch gedacht ist

Dieses Buch richtet sich an Softwarearchitekten, Backend- und Plattform-Ingenieure, technische Leiter und Entscheider, die ein Software-as-a-Service-Produkt entwerfen, betreiben oder skalieren. Es setzt solide Grundkenntnisse in verteilten Systemen, relationalen Datenbanken und mindestens einer Cloud-Plattform voraus. Wer bereits produktiv mit Mandantenmodellen arbeitet, findet in den späteren Teilen und den sechs Fallstudien den größten Mehrwert; wer neu in das Thema einsteigt, sollte mit Teil I und II beginnen.

Für wen dieses Buch nicht gedacht ist

Dieses Buch ist keine Einführung in Programmierung, Datenbanken oder Cloud-Grundlagen im Allgemeinen. Wer noch nie mit SQL, REST-APIs oder Container-Orchestrierung gearbeitet hat, wird an vielen Stellen den Anschluss verlieren. Ebenso wenig ist es ein Werkzeugvergleich im Sinne einer Kaufberatung; konkrete Produkte werden dort genannt, wo sie zur Illustration nötig sind, nicht als Empfehlung im Sinne eines Rankings.

Wie dieses Buch zu lesen ist

Die neun Teile sind aufeinander aufgebaut, aber nicht streng linear. Wer bereits ein produktives SaaS-System betreibt, kann problemlos mit Teil III (Datenisolation) oder Teil VI (Performance) einsteigen und bei Bedarf zu den Grundlagenkapiteln zurückspringen. Am Ende jedes Kapitels finden sich — bewusst unterschiedlich strukturiert — Praxishinweise: mal als Lessons Learned, mal als Entscheidungscheckliste, mal als Anti-Pattern-Katalog. Diese Uneinheitlichkeit ist Absicht. Kein reifes Systemdesign folgt einer Schablone; ein Fachbuch, das Systemdesign lehren möchte, sollte es genauso wenig tun.

Codebeispiele sind bewusst knapp gehalten. Sie illustrieren einen Punkt, sie ersetzen keine Bibliothek. Die vollständigen Beispiele stehen im begleitenden Repository zur Verfügung und werden dort auch aktualisiert, wenn sich Standards weiterentwickeln.

Typografische Konventionen

Kursivschrift markiert Fachbegriffe bei ihrer ersten Einführung sowie Buch- und Produktnamen. Fettschrift hebt Kernaussagen und Warnhinweise innerhalb eines Absatzes hervor. Technische Begriffe, die im Original meist englisch verwendet werden (z. B. Sharding, Tenant, Rate Limiting), bleiben unübersetzt, da eine deutsche Übersetzung in der Praxis kaum verwendet wird.

Code-Konventionen

Codebeispiele erscheinen in nichtproportionaler Schrift mit grauer Hintergrundfläche. Auslassungen innerhalb eines Beispiels sind mit „// …“ bzw. „# …“ gekennzeichnet. Sprachkennzeichnungen (SQL, Python, YAML, TypeScript u. a.) stehen, wo hilfreich, über dem jeweiligen Block. Beispiele sind auf das Wesentliche reduziert; produktionsreifer Code enthält zusätzlich Fehlerbehandlung, Logging und Tests, die hier aus Platzgründen entfallen.

Diagrammkonventionen

Diagramme sind als nummerierte Abbildungen mit Kapitelbezug eingefügt (z. B. Abbildung 4.2 für die zweite Abbildung in Kapitel 4). Durchgezogene Linien stehen für synchrone, gestrichelte Linien für asynchrone Kommunikation. Mandantengrenzen sind, wo relevant, als gepunkteter Rahmen dargestellt.

Versionshinweise

Alle Beispiele wurden gegen die zum Zeitpunkt der Drucklegung aktuellen Hauptversionen der genannten Werkzeuge geprüft (u. a. PostgreSQL 16, Kubernetes 1.29, OAuth 2.1). Da sich Schnittstellen und Best Practices weiterentwickeln, empfiehlt es sich, Versionsstände im begleitenden Repository zu prüfen, bevor Beispiele produktiv übernommen werden.

Danksagung

Dieses Buch verdankt seine praktische Schärfe den Teams, mit denen ich über die Jahre an mandantenfähigen Systemen gearbeitet habe — an ihren Fragen ebenso wie an ihren Fehlern, aus denen sich die meisten der hier versammelten Lektionen ableiten. Den Testlesern der frühen Kapitel danke ich für unbequeme, aber notwendige Rückmeldungen.

Teil I — Grundlagen

Der erste Teil legt das begriffliche und wirtschaftliche Fundament. Wer Mandantenfähigkeit später sauber implementieren möchte, muss zunächst verstehen, aus welcher Not SaaS entstanden ist, welche Kräfte es formen und welche Begriffe im Rest des Buches durchgängig verwendet werden.

Die drei Kapitel dieses Teils sind bewusst nicht überladen. Sie sollen die Sprache setzen, nicht die Antworten vorwegnehmen. Wer die Grundlagen bereits sicher beherrscht, kann direkt zu Teil II springen; die späteren Kapitel greifen die Begriffe konsistent auf.

Kapitel 1 — Die Evolution von SaaS

Von On-Premises zu Cloud-Diensten

Die Geschichte der Unternehmenssoftware ist eine Geschichte der Auslagerung. Zunächst wanderten Rechenzentren aus dem eigenen Keller in Colocation-Standorte. Später übernahm virtualisierte Infrastruktur die Rolle physischer Server. Schließlich verschluckten vollständig verwaltete Plattformdienste die letzten klassischen Betriebsaufgaben: Backup, Patch, Failover, Kapazitätsplanung. SaaS ist der konsequente Endpunkt dieser Bewegung. Der Kunde bezieht nicht mehr Infrastruktur, nicht mehr Middleware, nicht einmal eine Anwendung im klassischen Sinne, sondern eine fortlaufend gepflegte, versionierte Fähigkeit.

Diese Verschiebung ist mehr als ein Betriebsmodell. Sie verändert Vertragsstrukturen, prägt Release-Zyklen und definiert neu, was ein Softwareprodukt überhaupt ist. Wer heute ein CRM „kauft”, kauft in Wirklichkeit einen fortlaufenden Zugang zu einer Plattform, die sich unter ihm ständig verändert — manchmal spürbar, meistens unmerklich. Die Analogie zum Stromnetz ist alt, aber sie trifft: Niemand kauft ein Kraftwerk, jeder erwartet eine Steckdose.

Für Architekten bedeutet diese Verschiebung, dass klassische Erfolgskriterien — Funktionsumfang zum Release, Stabilität einer bestimmten Version — ergänzt werden durch Kennzahlen, die früher dem Betrieb vorbehalten waren: Verfügbarkeit, Latenz, Deployment-Frequenz, mittlere Wiederherstellungszeit. Die Software ist nicht mehr Produkt, sondern Dienstleistung. Und Dienstleistungen bewertet man an ihrer Verfügbarkeit, nicht an ihrer Verpackung.

Wirtschaftliche Treiber

SaaS setzte sich nicht durch, weil die Technologie eleganter war. Sie setzte sich durch, weil das Geschäftsmodell für beide Seiten überzeugend ist. Anbieter erhalten planbare wiederkehrende Umsätze, konsolidierte Betriebskosten und die Möglichkeit, aus aggregiertem Nutzungsverhalten schneller zu lernen als jeder Einzelkunde. Käufer entgehen große Vorabinvestitionen, mehrjährige Hardwarezyklen und die Verantwortung für Sicherheitsupdates.

Diese Vorteile funktionieren aber nur, wenn ein SaaS-Anbieter seine Marginalkosten pro Mandant niedrig hält. Genau hier beginnt die technische Diskussion, die dieses Buch trägt. Jede Isolationsstufe kostet Ressourcen. Jede geteilte Ressource birgt Risiken. Multi-Tenancy ist der ingenieurmäßige Versuch, beides in Balance zu bringen — oder, ehrlicher formuliert, ein Kompromiss, den man laufend neu justieren muss.

Production Tip — Architect’s Note

Die betriebswirtschaftliche Realität diktiert die technische Freiheit. Ein Produkt mit 200 € Monatsumsatz pro Mandant verträgt keine dedizierte Datenbank; ein Produkt mit 20.000 € Monatsumsatz pro Mandant wird sie oft ausdrücklich einfordern. Wer diese Zahl nicht kennt, sollte kein Tenancy-Modell diskutieren.

Der SaaS-Reifegrad

Ein hilfreiches, wenn auch grobes Modell zur Einordnung ist die Reifegradpyramide, die Microsoft bereits vor über einem Jahrzehnt geprägt hat. Stufe 1 beschreibt individuell gehostete Instanzen pro Kunde, Stufe 2 konfigurierbare Instanzen aus einem gemeinsamen Codestand, Stufe 3 vollständig mandantenfähige, zentral betriebene Systeme und Stufe 4 zusätzlich horizontal skalierbare Deployments. Die meisten seriösen SaaS-Angebote bewegen sich zwischen Stufe 3 und Stufe 4.

[Abbildung 1.1 — Die vier Stufen des SaaS-Reifegradmodells]

Ein häufiger strategischer Fehler besteht darin, aus Vertriebsgründen zu früh auf Stufe 1 zurückzufallen. Ein Großkunde wünscht eine dedizierte Umgebung, der Vertrieb sagt zu, und schon existiert eine Sonderlinie. Solche Ausnahmen führen fast immer zu einem verzweigten Betriebsmodell, das die Vorteile des SaaS-Ansatzes still und leise auffrisst. Nach zwei Jahren hat das Team drei Cluster, vier Deployment-Pipelines und einen Feature-Zweig, den sich niemand traut zu löschen.

Warum dieses Buch mit Wirtschaftlichkeit beginnt

Es gibt eine Reihe hervorragender technischer Bücher, die mit Diagrammen beginnen und mit Diagrammen enden. Dieses Buch nicht. Der Grund ist einfach: Fast jede Fehlentscheidung im Multi-Tenancy-Design, die ich in fünfundzwanzig Jahren gesehen habe, war zuerst eine Fehleinschätzung der wirtschaftlichen Rahmenbedingungen. Wer die Zahlen kennt, kommt zu belastbareren Architekturen als wer nur Muster kennt.

Lessons Learned

— Reifegrad ist kein Selbstzweck. Ein wachsendes Produkt wandert stufenweise nach oben, aber selten monoton — Ausnahmen für einzelne Kunden sind normal.

— Die Marginalkosten pro Mandant sind die wichtigste Zahl des Produkts. Sie fehlt in erschreckend vielen Architekturdokumenten.

— Eine „Enterprise-Edition” auf isolierter Infrastruktur ist ein legitimes Geschäftsmodell. Sie muss aber im Preis abgebildet und als eigenes Produkt-SKU geführt werden, nicht als Sonderfall in der Betriebsabteilung.

Kapitel 2 — Multi-Tenancy verstehen

Was ist eigentlich ein Mandant?

Der Begriff „Tenant” wirkt harmlos, verbirgt aber überraschende Fallstricke. In manchen Produkten entspricht ein Mandant genau einer Organisation. In anderen ist er eine Abteilung, ein Land, ein Projekt oder eine juristische Person innerhalb eines Konzerns. Bei einer HR-Suite kann der Konzern der Vertragspartner sein, während jede Landesgesellschaft eine eigene, isolierte Datensphäre haben soll. Bei einer Reiseplattform kann ein Tenant sogar eine einzelne natürliche Person sein.

Diese Definition ist keine technische Detailfrage. Sie beeinflusst Rechteverwaltung, Datenisolation, Abrechnung, Reporting und die Frage, wie Mandantenlöschungen ausgeführt werden. Ein früh gefasster, gut dokumentierter Tenant-Begriff spart Jahre späterer Refactorings.

Ich empfehle grundsätzlich, den Tenant explizit als eigene Domänen-Entität zu modellieren — mit klarer Identität, klarem Lebenszyklus (Provisionierung, Suspendierung, Kündigung, Löschung), klaren Beziehungen zu Benutzern, Verträgen und Ressourcen sowie klaren Ereignissen bei Zustandswechseln. Ein Tenant sollte nie eine Fußnote im Datenmodell sein.

Tenant, Organisation, Workspace: eine kleine Begriffsordnung

Die Praxis kennt drei überlappende Begriffe. „Tenant” ist die Isolationsgrenze aus Sicht der Architektur. „Organisation” ist die geschäftliche Einheit, mit der der Vertrag geschlossen wird. „Workspace” (oder „Project”, „Site”, „Environment”) ist die logische Arbeitsumgebung, in der Nutzer produktiv sind. In vielen Systemen fallen diese drei zusammen. In größeren Systemen fallen sie auseinander: Eine Organisation kann mehrere Workspaces haben, die technisch aber demselben Tenant angehören.

Wer diese drei Begriffe verwechselt, baut sich früher oder später eine Sackgasse. Ich habe mehrfach erlebt, wie ein „Workspace” nachträglich zum eigenen Tenant befördert werden musste, weil ein Kunde plötzlich getrennte Datenverantwortung pro Landesgesellschaft verlangte. Ohne saubere Trennung im Modell ist das eine mehrmonatige Migration.

Formen von Mandantenfähigkeit

Multi-Tenancy ist kein binärer Zustand. Sie kann auf verschiedenen Ebenen realisiert werden: auf Anwendungsebene (gemeinsame Prozesse), auf Datenbankebene (gemeinsame Schemas), auf Infrastrukturebene (geteilte Cluster) oder als Kombination davon. Reale Systeme sind fast immer hybrid: Der Anwendungsserver ist geteilt, die Datenbank teilweise isoliert, bestimmte Premium-Kunden erhalten dedizierte Ressourcen, während der Rest sich einen Pool teilt.

Diese Vielfalt ist kein Zeichen von schlechter Architektur, sondern von Realität. Ein System, das für alle Kunden dasselbe Modell erzwingt, verliert entweder margenschwache Kunden im Kleinsegment oder verliert regulierte Kunden im Enterprise-Segment.

Warnung

Die Formulierung „vollständige Datentrennung” auf Vertriebsfolien ist selten technisch präzise. Zumindest gemeinsam bleiben in aller Regel Betriebsteam, Deployment-Pipeline, Netzwerk und Monitoring. Ehrliche Kommunikation gegenüber Kunden zahlt sich langfristig aus — der Alternative ist ein peinliches Gespräch nach dem ersten unangekündigten Sicherheitsaudit.

Der Tenant-Lebenszyklus

Ein Tenant durchläuft eine überschaubare Reihe von Zuständen, die aber jeder für sich betriebliche Konsequenzen haben:

— Angelegt, noch nicht aktiviert. Nutzer registriert, aber keine Zahlung, keine Aktivierung. Häufig fehlen hier später die Aufräumroutinen; das System sammelt Zombie-Tenants an.

— Aktiv. Der Normalzustand. Alle Ressourcen sind provisioniert, alle Quoten greifen.

— Suspendiert. Etwa wegen Zahlungsverzugs. Daten bleiben erhalten, Zugriff wird verweigert. Wichtig: Suspendierung darf keine irreversiblen Löschungen auslösen.

— Gekündigt. Der Kunde hat den Vertrag beendet. Daten bleiben typischerweise noch 30–90 Tage aufbewahrt.

— Gelöscht. Endgültige Entfernung inklusive Backups, Suchindizes, Caches und Data-Warehouse-Kopien.

[Abbildung 2.1 — Zustandsdiagramm des Tenant-Lebenszyklus]

Wer diesen Lebenszyklus nicht explizit modelliert, verwaltet ihn mit Booleans, Nullwerten und Kommentarfeldern — und wundert sich, warum die Compliance-Abteilung nach jedem Audit unglücklich ist.

Design Review: Tenant-Modell in Kürze

Eine kurze Checkliste, die ich in jeder Architekturbewertung anwende:

— Existiert eine explizite Tenant-Entität mit stabiler ID?

— Ist der Tenant-Lebenszyklus dokumentiert und in Code abgebildet?

— Kennt jede querschnittliche Komponente — Auth, Logging, Metrics, Billing — den Tenant-Kontext?

— Gibt es einen dokumentierten Prozess für Tenant-Löschung inklusive Backups?

— Sind Tenant-IDs in URLs bewusst wählbar (Slug) oder nicht (UUID)? Beide sind legitim, aber die Entscheidung muss bewusst sein.

Kapitel 3 — Herausforderungen und Zielkonflikte

Die zentralen Spannungsfelder

Beim Entwurf mandantenfähiger Systeme kollidieren regelmäßig dieselben Ziele: Kostenoptimierung gegen Isolation, Betriebsvereinfachung gegen individuelle Konfigurierbarkeit, gleichbleibende Performance gegen hohe Ressourcenauslastung, schnelle Releases gegen regulatorische Kontrollpflichten. Diese Konflikte lassen sich nicht auflösen. Sie lassen sich nur bewusst austarieren — und diese Justierung ist selten dauerhaft, weil sich Kundenmix, Regulierung und Konkurrenzsituation über die Jahre verschieben.

Erfahrene Teams halten die getroffenen Kompromisse in Architekturentscheidungsprotokollen (ADRs) fest. Diese Praxis wirkt bürokratisch, spart aber später endlose Grundsatzdiskussionen. Wer eine Entscheidung nicht in einer halben Seite schriftlich begründen kann, hat sie meist nicht ausreichend durchdacht. Ein ADR ist kein Bittbrief an eine Prozesspolizei, sondern eine Notiz an das eigene zukünftige Ich, das sich in zwei Jahren fragen wird, warum wir uns damals so entschieden haben.

Ein Kaminfeuergespräch zweier Architekten

Um die Spannungsfelder greifbarer zu machen, folgt hier ein fiktives, aber sehr realitätsnahes Gespräch zwischen zwei Architekten — einem, der ein junges Produkt begleitet (A), und einer, die eine reife Plattform betreibt (B). Es fasst zusammen, was in vielen Reviews wortwörtlich fällt.

A: Wir überlegen, jedem Kunden ein eigenes Schema zu geben. Sicherheitsseitig wirkt das sauberer.

B: Wie viele Kunden habt ihr?

A: Achtzig, mit Sicht auf tausend.

B: Und wer betreibt später die Migrationen?

A: Das automatisieren wir.

B: Automatisieren ist einfach zu sagen. Wir hatten dreitausend Schemas und dreiunddreißig Minuten Migrationsfenster. Das reicht nicht. Man macht das nur, wenn man es unbedingt braucht — nicht, weil es sauberer wirkt.

A: Was hättest du getan?

B: Shared Schema mit RLS. Verschlüsselung auf sensiblen Feldern. Eine kleine Enterprise-Linie mit dedizierter Datenbank für die drei Kunden, die es verlangen. Alles andere ist Ingenieurshochmut.

Solche Gespräche sind keine Anekdoten; sie sind der eigentliche Kern des Handwerks. Kein Muster ist per se richtig. Es ist richtig für einen bestimmten Kundenzuschnitt, ein bestimmtes Volumen, einen bestimmten regulatorischen Rahmen.

Häufige Fehleinschätzungen

— „Wir migrieren später auf Datenbank pro Mandant.” In der Regel nicht ohne substanzielle Umbauten möglich. Wer schon einmal einen Foreign Key über zwei Datenbanken hinweg nachträglich auflösen musste, weiß, was gemeint ist.

— „Ein Feature-Flag reicht als Isolation.” Feature-Flags trennen Sichtbarkeit, nicht Daten. Sie sind ein Werkzeug für Deployment, kein Sicherheitsmechanismus.

— „Wir brauchen jetzt noch keinen Tenant-Kontext.” Nachträgliche Einführung verursacht überproportional viele Fehler, weil hunderte von Abfragen retroaktiv um einen Filter ergänzt werden müssen.

— „RLS ist zu langsam für unser Volumen.” Meist stimmt das nicht; oft fehlen lediglich passende Indizes oder die Session-Variable wird pro Query neu gesetzt statt pro Transaktion.

— „Isolation regelt schon das Kubernetes-Namespace.” Nein. Ein Namespace ist keine Sicherheitsgrenze im starken Sinne.

Anti-Patterns aus der Praxis

Ein kleines Bestiarium wiederkehrender Fehlentwürfe, die ich mehr als einmal gesehen habe:

— Die tenant_id als Query-Parameter. Manipulierbar, nachrangig authentifiziert, katastrophal. Der Tenant gehört ins Token, niemals in die URL.

— Der geteilte Cache ohne Präfix. Ein Bug in der Serialisierung, und Kunde A sieht den Warenkorb von Kunde B. Immer mit Tenant-Präfix arbeiten.

— Die „Debug-Rolle” mit BYPASSRLS. Wird für einen Wartungsvorgang eingerichtet, bleibt für immer bestehen, wird irgendwann auch von der Anwendung genutzt.

— Die kundenspezifische Konfiguration im Code. if (tenantId == „kunde-x”) doSomethingSpecial() — der Anfang jeder unwartbaren Codebasis.

Anti-Pattern — Der kritischste Fall

Von den vier genannten Mustern ist die tenant_id als Query-Parameter das gefährlichste, weil es sich am einfachsten in einem Penetrationstest findet — und am einfachsten von jedem angemeldeten Nutzer ausnutzen lässt, der einfach eine Zahl in der URL ändert. Diese Klasse von Fehlern gehört in jeden Code-Review als hartes Ablehnungskriterium, nicht als Verbesserungsvorschlag.

Entscheidungscheckliste vor dem ersten Codebeispiel

Bevor eine Zeile geschrieben wird, sollten diese Punkte beantwortet sein:

— Ist der Tenant klar definiert? Wer ist es, wer nicht?

— Welche Isolationsstufe verlangen die drei anspruchsvollsten Kunden?

— Welche Marginalkosten kann ein Mandant maximal verursachen, bevor er unrentabel wird?

— Welche Compliance-Anforderungen sind bereits jetzt vertraglich zugesagt?

— Wer betreibt das System operativ? Welche Werkzeuge existieren bereits?

Wer diese fünf Fragen nicht beantworten kann, sollte keine Entscheidung zwischen Shared-Everything und Database-per-Tenant treffen. Wer sie beantworten kann, wird oft feststellen, dass die Entscheidung sich fast von selbst ergibt.

FAQ

Muss ich mich für ein einziges Tenancy-Modell entscheiden?

Nein, und in der Praxis tun das die wenigsten Anbieter. Die meisten reifen SaaS-Systeme fahren ein Basismodell für den Großteil der Kunden und eine abweichende, bewusst dokumentierte Linie für einzelne Enterprise-Verträge.

Wie früh sollte der Tenant-Kontext eingeführt werden?

Ab dem ersten Datenbankschema. Die Kosten einer nachträglichen Einführung steigen mit jeder Tabelle, die ohne Tenant-Spalte angelegt wird.

Ist ein Kubernetes-Namespace pro Mandant eine Form von Isolation?

Nur eine schwache. Namespaces trennen administrativ, nicht sicherheitskritisch — dafür braucht es zusätzlich NetworkPolicies, eigene Service-Accounts und, je nach Anforderung, eigene Nodes.

Teil II — Tenancy-Modelle

Dieser Teil widmet sich den grundlegenden Architekturvarianten, mit denen Mandantenfähigkeit realisiert werden kann. Für jedes Modell werden Architektur, Vor- und Nachteile, Kosten, Skalierbarkeit, Sicherheit, betriebliche Komplexität und typische Einsatzszenarien besprochen.

Wichtig vorweg: Diese Modelle sind keine Sekten, denen man beitritt. Sie sind Werkzeuge, die man kombiniert. Der letzte Abschnitt dieses Teils widmet sich deshalb ausdrücklich hybriden Modellen, weil sie in produktiven Systemen die Regel und nicht die Ausnahme sind.

Kapitel 4 — Shared Everything

Architektur

Beim Shared-Everything-Ansatz teilen sich alle Mandanten dieselben Anwendungsinstanzen, dieselbe Datenbank, dieselben Schemas und häufig sogar dieselben Caches. Die Zuordnung zum Mandanten erfolgt ausschließlich über eine Tenant-ID, die in jeder relevanten Tabelle als Spalte vorhanden ist und in jeder Abfrage explizit gefiltert werden muss — oder, deutlich empfehlenswerter, durch einen strukturellen Mechanismus wie PostgreSQL Row-Level Security automatisch angewendet wird.

Dieses Modell ist maximal effizient und maximal riskant zugleich. Effizient, weil jede Ressource ideal ausgelastet werden kann und die Grenzkosten für einen weiteren kleinen Mandanten fast null sind. Riskant, weil ein einziger vergessener Filter genügt, um Daten aus dem falschen Kontext offenzulegen. Die gute Nachricht: Dieses Risiko lässt sich mit den in Kapitel 8 und Kapitel 9 beschriebenen Techniken strukturell nahezu eliminieren.

Warum das Standardmodell trotzdem gewinnt

Wenn man ehrlich zurückblickt, sind die erfolgreichsten SaaS-Plattformen der letzten fünfzehn Jahre — Salesforce, Slack, Notion, HubSpot, Shopify — im Kern Shared-Everything-Systeme mit sorgfältig ausgewählten Ausnahmen. Der Grund ist nicht Bequemlichkeit, sondern Wirtschaftlichkeit. Ein Modell, das den langen Schwanz kleiner und mittlerer Kunden zu vertretbaren Kosten bedient, lässt sich mit Enterprise-Ausnahmen ergänzen. Ein Modell, das Enterprise-Kunden mit dedizierter Infrastruktur bedient, lässt sich fast nie wieder in die Wirtschaftlichkeit des Long Tail zurückführen.

Vergleich der Tenancy-Modelle

Umsetzung mit PostgreSQL Row-Level Security

ALTER TABLE invoices ENABLE ROW LEVEL SECURITY;


CREATE POLICY tenant_isolation ON invoices

USING (tenant_id = current_setting(„app. tenant_id”)::uuid);


— Bei jedem Verbindungswechsel oder Transaktionsbeginn:

SET LOCAL app. tenant_id = „5f0e3d8a-…”;

Der entscheidende Detailpunkt: SET LOCAL bindet die Variable an die aktuelle Transaktion. Wer stattdessen SET ohne LOCAL nutzt, klebt die Tenant-ID an die physische Verbindung — ein Fehler, der bei Connection-Poolern wie PgBouncer im Transaction-Mode zu genau der Datenüberlagerung führt, die RLS eigentlich verhindern soll.

Best Practice

Setzen Sie den Tenant-Kontext in einer Verbindungs-Middleware auf Anwendungsebene, nicht in einzelnen Repositories. Der Fehler „einmal vergessen” ist dann strukturell ausgeschlossen. Testen Sie diesen Mechanismus mit einer bewusst nicht gesetzten Tenant-ID; die Abfrage muss dann einen Fehler werfen oder null Zeilen zurückliefern, nie stumm alle Zeilen ausgeben.

Skalierungspfad

Ein reines Shared-Everything-System skaliert horizontal, solange die Datenbank mitkommt. Sobald die zentrale Datenbank zum Engpass wird, gibt es drei Pfade, die üblicherweise in dieser Reihenfolge beschritten werden: Read-Replikas für Lesevolumen, Partitionierung großer Tabellen nach Tenant-ID, schließlich Sharding auf mehrere physische Datenbanken. Kapitel 22 beschreibt diese Pfade im Detail.

Typische Einsatzszenarien

Startphase eines Produkts, kostensensitive Segmente, große Anzahl kleiner Mandanten mit ähnlichen Nutzungsprofilen, klassisches B2B-SaaS im mittleren Preissegment. Kaum geeignet für regulierte Umgebungen ohne begleitende Verschlüsselung und ohne physisch getrennte Ausnahmen für die anspruchsvollsten Kunden.

Wann Shared Everything nicht die richtige Wahl ist

— Wenn ein einzelner Kunde mehr als etwa zehn Prozent des Systemvolumens ausmacht. Das Noisy-Neighbor-Risiko wird dann zum Dauerthema.

— Wenn Regulierung dedizierte Verschlüsselungsschlüssel pro Mandant verlangt und Krypto-Shredding als Löschverfahren ausgeschlossen ist.

— Wenn Kunden vertraglich physische Trennung fordern und diese Forderung nicht mit einer Enterprise-Sonderlinie bedient werden kann.

Kapitel 5 — Shared Database, Separate Schemas

Idee

Beim Schema-pro-Mandant-Ansatz existiert weiterhin eine einzige physische Datenbankinstanz, doch jeder Mandant erhält ein eigenes logisches Schema. Migrationsskripte müssen jedes Schema durchlaufen; Abfragen setzen den korrekten Suchpfad. Der Ansatz bietet eine mittlere Isolationsstufe und ist besonders bei zwei Anforderungen attraktiv: separaten Backups pro Kunde und Reporting-Aufgaben, die schemaweit ohne Tenant-Filter arbeiten sollen.

Der bekannteste Fallstrick ist die Skalierung. Jenseits weniger tausend Schemas werden PostgreSQL-Systemkataloge spürbar langsamer, Migrationslaufzeiten explodieren, Verbindungspools müssen umsichtig konfiguriert werden. Was auf einer Testinstanz mit 50 Schemas problemlos funktioniert, kann auf einer Produktivinstanz mit 5.000 Schemas zur Katastrophe werden.

Warum dieses Modell überschätzt wird

Das Schema-pro-Mandant-Modell wird gerne als „Isolation ohne die Kosten von DB-per-Tenant” verkauft. Diese Rechnung geht selten auf. Denn die Isolation ist trügerisch: Ein Bug im Anwendungscode kann sehr wohl den Suchpfad falsch setzen. Und die Betriebskosten sind höher, als sie auf den ersten Blick wirken — jede Migration muss auf jedes Schema laufen, jede Schemaänderung ist ein potenzieller Blocker für neue Kunden.

Für regulierte Nischen mit wenigen dutzend Mandanten ist das Modell attraktiv. Für ein wachsendes SaaS mit tausenden Kunden ist es fast immer der falsche Kompromiss — zu viel Betriebsaufwand für zu wenig zusätzliche Isolation im Vergleich zu Shared-Everything mit RLS.

Migrationsstrategie

from concurrent. futures import ThreadPoolExecutor


def migrate_tenant(tenant):

with pool.connection() as conn:

conn. execute(f"SET search_path TO tenant_{tenant.id}”)

liquibase. update(conn)

record_progress(tenant.id, „ok”)


with ThreadPoolExecutor(max_workers=8) as ex:

for tenant in tenants:

ex.submit(migrate_tenant, tenant)

Die Zahl der parallelen Worker muss zu den Kapazitäten der Datenbank passen. Acht bis sechzehn parallele Migrationen sind bei modernen Cloud-Datenbanken üblich; darüber hinaus dominiert die Sperrsituation der Systemkataloge.

Common Mistake

Migrationen sequenziell über tausende Schemas laufen zu lassen. Bei zehn Sekunden pro Schema und viertausend Schemas ergibt das über elf Stunden Fenster. Nutzen Sie parallele Worker mit begrenzter Konkurrenz, ein Fortschrittsprotokoll je Mandant und die Fähigkeit, an einer beliebigen Stelle wieder aufzusetzen.

Praktische Entscheidungshilfe

— Weniger als 100 Mandanten und stabile Datenmengen? Schema-pro-Mandant kann sinnvoll sein.

— Zwischen 100 und 1.000 Mandanten? Vergleichen Sie ehrlich mit Shared-Everything plus RLS.

— Mehr als 1.000 Mandanten? Wählen Sie entweder Shared-Everything mit Partitionierung oder DB-pro-Tenant, aber nicht Schema-pro-Mandant.

FAQ

Kann ich später von Schema-pro-Mandant auf DB-pro-Tenant migrieren? Ja, weil die Zugriffsschicht meist bereits Tenant-aware ist. Der Aufwand steckt im Verbindungsmanagement und in der Migration von Suchindizes.

Wie handhabe ich Cross-Tenant-Reports? Über eine dedizierte Analytics-Datenbank (ClickHouse, Snowflake, BigQuery), die per CDC gefüllt wird. Direkte Cross-Schema-Joins in der OLTP-Datenbank sind fast immer eine schlechte Idee.

Was ist mit gemeinsamen Stammdaten wie Ländern oder Währungen? In ein eigenes „shared” Schema legen, das aus jedem Tenant-Schema referenziert werden darf.

Kapitel 6 — Database per Tenant

Vollständige physische Trennung

Für stark regulierte Umgebungen — etwa Banken, Krankenhäuser, öffentliche Auftraggeber — ist eine eigene Datenbank pro Mandant oft nicht Kür, sondern Pflicht. Sie ermöglicht dedizierte Verschlüsselungsschlüssel, granulare Backups, unabhängige Wiederherstellungspunkte und regional getrennte Speicherorte. Sie erlaubt außerdem, einzelnen Kunden individuelle Wartungsfenster zuzusagen — ein Verkaufsargument, das im Enterprise-Segment mehr wiegt, als Techniker gerne glauben.

Diesen Vorteilen stehen erhebliche Betriebskosten gegenüber. Verbindungspools müssen pro Datenbank verwaltet werden. Schemamigrationen benötigen orchestrierte Rollout-Strategien. Das Monitoring vervielfacht sich linear mit der Mandantenzahl. Backups, Alerting-Regeln und Kapazitätsplanung werden zu Themen, die pro Mandant behandelt werden müssen — aus einer Aufgabe werden hunderte.

Wann sich der Aufwand lohnt

Als grobe Faustregel: Wenn der jährliche Vertragswert pro Mandant sechsstellig ist und Regulierung physische Trennung verlangt, ist DB-pro-Tenant angemessen. Wenn der Vertragswert vierstellig ist, ist es fast immer die falsche Wahl — die Betriebskosten fressen die Marge.

Verbindungsmanagement in Node. js

const pools = new Map<string, Pool>();


function getPool(tenantId: string): Pool {

const cached = pools.get(tenantId);

if (cached) return cached;


const pool = new Pool({

connectionString: buildConnString(tenantId),

max: 5,

idleTimeoutMillis: 30_000,

// Wichtig: application_name für Diagnose pro Tenant

application_name: „orders-service:${tenantId}”,

});

pools.set(tenantId, pool);

return pool;

}


// Regelmäßig inaktive Pools schließen, sonst wächst die Verbindungslast

setInterval(() => {

for (const [tenantId, pool] of pools) {

if (pool.totalCount === 0 && Date.now() — pool.lastUsed > 300_000) {

pool. end();

pools.delete(tenantId);

}

}

}, 60_000);

Der scheinbar harmlose Punkt „inaktive Pools schließen” ist in der Praxis der wichtigste. Ohne ihn wächst die Zahl der offenen Verbindungen unbegrenzt, und irgendwann bricht die Datenbank unter der Verbindungslast zusammen, bevor sie unter der Query-Last zusammenbrechen könnte.

Production Tip

Beobachten Sie die Gesamtzahl offener Datenbankverbindungen wie einen Kernindikator. Sobald sie mit der Zahl der Mandanten linear wächst, ist ein Reverse-Proxy wie PgBouncer im Transaction-Mode nahezu alternativlos. Er reduziert Server-Verbindungen um ein bis zwei Größenordnungen.

Operativer Preis

Die konkreten Zahlen, die man in DB-pro-Tenant-Setups sieht, sind ernüchternd. Ein reifes Team mit guter Automatisierung verwaltet 200–500 Datenbanken pro Vollzeitäquivalent im Betrieb. Ohne Automatisierung sind es 20–50. Wer diesen Multiplikator im Business-Case ignoriert, erlebt Überraschungen.

Migration Strategy

Ein häufiges Szenario: Ein wichtiger Kunde soll aus dem Shared-Cluster in eine dedizierte Datenbank umziehen. Bewährt hat sich ein vierstufiger Prozess:

— Dual-Write-Phase. Neue Schreibvorgänge landen in beiden Systemen.

— Backfill. Ein Job kopiert historische Daten in die neue Datenbank.

— Verifikation. Ein Vergleichslauf validiert Zeilenanzahl und Prüfsummen pro Tabelle.

— Umschaltung. Der Lese-Pfad wird umgestellt, dann der Schreib-Pfad, dann das alte Schema gelöscht.

Jede dieser Phasen ist rollback-fähig. Insbesondere die Dual-Write-Phase sollte lange genug laufen, dass mindestens ein vollständiges Backup gezogen und getestet wurde.

Kapitel 7 — Hybride Modelle

Motivation

In der Praxis sind rein einheitliche Modelle selten. Die meisten reifen SaaS-Plattformen kombinieren einen kostengünstigen Shared-Ansatz für die Mehrheit der Kunden mit dedizierten Umgebungen für einzelne Enterprise-Kunden. Entscheidend ist, diese Ausnahmen als Erstklasse-Konzept zu behandeln, nicht als operativen Sonderfall.

Ein tragfähiger Ansatz besteht darin, „Deployment-Rings” zu definieren: Ring 0 = Shared, Ring 1 = dediziertes Schema, Ring 2 = dedizierte Datenbank, Ring 3 = dediziertes Cluster oder eigene Region. Jede Erhöhung des Rings wird versioniert, dokumentiert und in die Preisgestaltung eingerechnet. Der Umzug zwischen Ringen ist ein definierter, wiederholbarer Prozess — kein Manuskript im Confluence-Wiki, das jedes Mal neu geschrieben wird.

Design Review: Rings als Produkt

Ein Ring ist kein technisches Detail, sondern eine Produkteigenschaft. Marketing, Vertrieb, Support und Betrieb müssen wissen, welche Rings existieren, was sie kosten und welche SLAs damit einhergehen. Sobald diese Klarheit fehlt, verkauft der Vertrieb Kombinationen, die niemand betreiben kann — ein „Ring 2 mit Ring 0 Update-Frequenz” oder ein „Ring 3 zum Ring-1-Preis”. Solche Sonderwünsche zerstören Wirtschaftlichkeit und Betriebsstabilität gleichzeitig.

Beispiel eines Rings-Modells

Migration Strategy

Der Umzug zwischen Rings sollte automatisiert sein und in einem Werkzeug abgebildet werden — nicht in einer Wiki-Seite. Typische Bausteine sind Datenbank-Kopiervorgänge, DNS-Wechsel, Aktualisierung von Konfigurationsspeichern und ein definiertes Downtime-Fenster (bei richtiger Auslegung wenige Minuten).

Anti-Patterns

— Ring-Kreuzung. Ein einzelner Kunde erhält Attribute mehrerer Rings („Ring 2 mit wöchentlichen Updates”). Führt zu Betriebs-Chaos.

— Undokumentierte Ausnahmen. Der Kunde X wurde einmal manuell auf einen anderen Cluster verschoben; niemand weiß mehr, wie oder warum.

— Ring-Inflation. Der Vertrieb verspricht regelmäßig Ring 3 zum Ring-1-Preis. Ohne strikte Governance verwässert das Modell in wenigen Quartalen.

Common Mistake — Ring-Inflation

Von den drei genannten Fällen ist die Ring-Inflation der teuerste, weil sie sich nicht in einem einzelnen Vorfall zeigt, sondern schleichend über Quartale. Jede einzelne Ausnahme wirkt vertretbar; in der Summe erodiert sie die Preislogik, auf der das gesamte Ring-Modell beruht. Governance — ein einziger Freigabepfad für Sonderkonditionen — ist hier wichtiger als jede technische Gegenmaßnahme.

Wann kein Hybrid-Modell nötig ist

Nicht jede Plattform braucht Rings. Ein reines Selbstbedienungs-SaaS ohne Enterprise-Kunden lebt mit einem einzigen Modell besser. Rings sind eine Antwort auf ein sehr spezifisches Problem: heterogene Kundenanforderungen bei signifikanten Preisunterschieden. Wer diese Heterogenität nicht hat, sollte die zusätzliche Komplexität nicht einführen.

Teil III — Datenisolation

Przeczytałeś bezpłatny fragment.
Kup książkę, aby przeczytać do końca.
E-book
za 23.63
drukowana A5
za 56.16