Wie Mehrmandanten-Datenbanken Sicherheit und Performance beeinflussen
Erfahre, wie Mehrmandanten-Datenbanken Sicherheit und Performance beeinflussen, welche Risiken (Isolation, Noisy Neighbors) bestehen und welche praktischen Maßnahmen Mandanten sicher und performant halten.

Was eine Mehrmandanten-Datenbank bedeutet
Eine Mehrmandanten-Datenbank ist eine Architektur, bei der viele Kunden (Mandanten) dasselbe Datenbanksystem teilen — denselben Datenbankserver, denselben zugrundeliegenden Speicher und oft dasselbe Schema — während die Anwendung dafür sorgt, dass jeder Mandant nur seine eigenen Daten sehen kann.
Stell es dir wie ein Wohnhaus vor: alle teilen die Struktur und Versorgungsleitungen, aber jeder Mandant hat seine eigene verschlossene Einheit.
Mehrmandantig vs. Einzelnutzung (auf hohem Niveau)
In einem Single-Tenant-Ansatz bekommt jeder Kunde dedizierte Datenbankressourcen — zum Beispiel eine eigene Datenbankinstanz oder einen eigenen Server. Die Isolation ist einfacher nachzuvollziehen, aber meist teurer und betrieblich aufwendiger, wenn die Kundenzahl wächst.
Bei Mehrmandantigkeit teilen sich Mandanten die Infrastruktur, was effizient sein kann — es bedeutet aber auch, dass dein Design Grenzen bewusst durchsetzen muss.
Warum SaaS-Teams Mehrmandanten wählen
SaaS-Firmen entscheiden sich aus praktischen Gründen oft für Mehrmandanten:
- Niedrigere Kosten pro Kunde (gemeinsame Compute-, Speicher- und Lizenzkosten sowie weniger Betriebsaufwand)
- Einfacherer Betrieb in großem Maßstab, z. B. weniger Datenbanken, die gepatcht, upgegradet und überwacht werden müssen
- Schnelleres Onboarding neuer Kunden (kein komplettes Provisioning einer Datenbankumgebung)
Die zentrale Erwartung: Design bestimmt das Ergebnis
Mehrmandantigkeit ist nicht automatisch „sicher“ oder „schnell“. Das Ergebnis hängt von Entscheidungen ab, z. B. wie Mandanten getrennt werden (Schema, Zeilen, oder Datenbanken), wie Zugriffskontrolle durchgesetzt wird, wie Verschlüsselungsschlüssel gehandhabt werden und wie verhindert wird, dass die Last eines Mandanten andere verlangsamt.
Der Rest dieses Leitfadens konzentriert sich auf diese Design-Entscheidungen — denn in Mehrmandantensystemen sind Sicherheit und Performance Funktionen, die du baust, keine Annahmen, die du übernimmst.
Gängige Mehrmandanten-Datenbank-Modelle
Mehrmandantigkeit ist keine einzelne Designwahl — es ist ein Spektrum, wie eng du Infrastruktur teilst. Das gewählte Modell definiert deine Isolationsgrenze (was niemals geteilt werden darf) und beeinflusst direkt Datenbanksicherheit, Performance-Isolation und den täglichen Betrieb.
Datenbank-pro-Mandant
Jeder Mandant bekommt seine eigene Datenbank (oft auf demselben Server oder Cluster).
Isolationsgrenze: die Datenbank selbst. Das ist in der Regel die sauberste Isolation, weil cross-mandant Zugriff normalerweise das Überschreiten der Datenbankgrenze erfordert.
Operative Trade-offs: aufwändiger im Betrieb bei großer Anzahl von Mandanten. Upgrades und Schema-Migrationen müssen vielleicht tausendfach ausgeführt werden, und Connection-Pooling kann komplizierter werden. Backups/Restores sind pro Mandant einfach, aber Speicher- und Verwaltungsaufwand kann schnell wachsen.
Sicherheit & Tuning: im Allgemeinen am leichtesten pro Kunde zu sichern und zu optimieren; gut geeignet, wenn Mandanten unterschiedliche Compliance-Anforderungen haben.
Schema-pro-Mandant
Mandanten teilen eine Datenbank, aber jeder Mandant hat sein eigenes Schema.
Isolationsgrenze: das Schema. Es ist eine sinnvolle Trennung, hängt aber von korrekten Rechten und Tooling ab.
Operative Trade-offs: Upgrades und Migrationen sind weiterhin repetitiv, aber weniger aufwendig als bei Datenbank-pro-Mandant. Backups sind kniffliger: viele Tools behandeln die Datenbank als Backup-Einheit, sodass mandantenspezifische Operationen Schema-Exporte erfordern können.
Sicherheit & Tuning: leichter zu isolieren als geteilte Tabellen, aber diszipliniert mit Rechten und Query-Paths umgehen.
Tabelle-pro-Mandant
Alle Mandanten teilen eine Datenbank und ein Schema, aber jeder Mandant hat eigene Tabellen (z. B. orders_tenant123).
Isolationsgrenze: die Tabellensammlung. Kurzfristig praktikabel, aber schlecht skalierbar: Metadaten-Aufblähung, unhandliche Migrationsskripte und schlechtere Queryplanung können auftreten.
Sicherheit & Tuning: Berechtigungen können präzise sein, doch die operative Komplexität ist hoch und Fehler beim Hinzufügen neuer Tabellen oder Features passieren leicht.
Geteilte Tabellen (gemeinsames Schema)
Alle Mandanten teilen dieselben Tabellen, unterschieden durch eine tenant_id-Spalte.
Isolationsgrenze: deine Query- und Zugriffskontrollschicht (häufig Row-Level Security). Dieses Modell ist operativ effizient — ein Schema zu migrieren, eine Indexstrategie zu verwalten — es ist aber am anspruchsvollsten für Datenbanksicherheit und Performance-Isolation.
Sicherheit & Tuning: am schwersten korrekt umzusetzen, weil jede Abfrage mandantenbewusst sein muss. Das Noisy-Neighbor-Problem ist wahrscheinlicher, es sei denn, du ergänzt Resource-Throttling und sorgfältiges Index-Design.
Eine nützliche Regel: je mehr du teilst, desto einfacher werden Upgrades — aber desto mehr Strenge brauchst du bei Mandanten-Isolation und Performance-Schutzmaßnahmen.
Wie Mehrmandantigkeit das Sicherheitsmodell verändert
Mehrmandantigkeit heißt nicht nur „mehrere Kunden in einer Datenbank“. Sie verändert dein Bedrohungsmodell: das größte Risiko verschiebt sich von Außenangriffen hin zu autorisierter Nutzung, die versehentlich (oder absichtlich) Daten eines anderen Mandanten sichtbar macht.
Authentifizierung vs. Autorisierung: Mandantenkontext ist eine Autorisationsentscheidung
Authentifizierung beantwortet „Wer bist du?“. Autorisierung beantwortet „Was darfst du zugreifen?“. In einer Mehrmandanten-Datenbank muss der Mandantenkontext (tenant_id, account_id, org_id) bei der Autorisierung durchgesetzt werden — und darf nicht als optionaler Filter behandelt werden.
Ein häufiger Fehler ist das Annehmen, dass wenn ein Benutzer authentifiziert ist und „sein Mandant bekannt ist“, die Anwendung automatisch Abfragen trennt. In der Praxis muss Trennung explizit und an einer konsistenten Kontrollstelle erzwungen werden (z. B. Datenbank-Policies oder eine obligatorische Abfrage-Schicht).
Kernregel: Jede Lese- und Schreiboperation muss mandantengebunden sein
Die einfachste Regel ist zugleich die wichtigste: Jeder SELECT und jede Änderung muss genau auf einen Mandanten eingeschränkt sein.
Das gilt für:
- SELECTs (einschließlich Listenseiten und Exporte)
- UPDATE/DELETE-Operationen
- Hintergrundjobs und ETL-Skripte
- Admin-Tools und Support-Workflows
Wenn Mandanten-Scoping optional ist, wird es irgendwann übersprungen.
Häufige Fehlerquellen, die Cross-Mandanten-Zugriff verursachen
Cross-Mandanten-Leaks entstehen oft durch kleine, alltägliche Fehler:
- Fehlende Mandantenfilter in einem Endpoint oder Codepfad
- „Kaputte“ Joins, bei denen eine Tabelle scoped ist, die verknüpfte aber nicht
- Caches, die nur nach Benutzer oder URL keyen, nicht nach Mandant
- Wiederverwendete Prepared Statements, die versehentlich die falsche
tenant_idbinden
Warum „es funktioniert in Tests“ trotzdem in Produktion leaken kann
Tests laufen typischerweise mit kleinen Datensätzen und sauberen Annahmen. Die Produktion bringt Konkurrenz, Retries, Caches, gemischte Mandantendaten und echte Edge-Cases.
Eine Funktion kann Tests bestehen, weil in der Testdatenbank nur ein Mandant existiert oder Fixtures keine überlappenden IDs enthalten. Sicherere Designs machen es schwer, eine ungetaggte Abfrage überhaupt zu schreiben, anstatt sich darauf zu verlassen, dass Reviewer jeden Fehler finden.
Isolationskontrollen, die Cross-Mandant-Zugriff verhindern
Das Kernrisiko in einer Mehrmandanten-Datenbank ist simpel: eine Abfrage, die vergisst nach Mandant zu filtern, kann fremde Daten preisgeben. Starke Isolation geht davon aus, dass Fehler passieren werden, und macht diese Fehler harmlos.
Mandantenkennzeichen und strikte Scoping-Pattern
Jeder mandantenbesitzte Datensatz sollte ein Mandantenkennzeichen tragen (z. B. tenant_id) und deine Zugriffsschicht sollte immer Lese- und Schreibvorgänge danach einschränken.
Ein praktisches Muster ist „Mandantenkontext zuerst“: die Anwendung ermittelt den Mandanten (aus Subdomain, Org-ID oder Token-Claims), speichert ihn im Request-Kontext, und dein Datenzugriffs-Code verweigert die Ausführung ohne diesen Kontext.
Hilfreiche Guardrails:
- Fordere
tenant_idin Primär-/Unique-Keys, wo angemessen (um Kollisionen zwischen Mandanten zu verhindern).\n- Füge Foreign Keys hinzu, dietenant_identhalten, damit mandantenübergreifende Beziehungen nicht versehentlich entstehen.
Row-Level Security (RLS) und policy-basierter Zugriff
Wo unterstützt (insbesondere PostgreSQL), kann Row-Level Security Mandantenprüfungen in die Datenbank verlegen. Policies können SELECT/UPDATE/DELETE so einschränken, dass nur Zeilen sichtbar sind, die zum aktuellen Mandanten passen.
Das reduziert die Abhängigkeit davon, dass jeder Entwickler die WHERE-Klausel korrekt setzt, und schützt gegen bestimmte Injection- oder ORM-Fehlgebrauch-Szenarien. Betrachte RLS als zweite Sperre, nicht als alleinige Schutzmaßnahme.
Schema-/Datenbank-Trennung als Isolationstool
Wenn Mandanten sensibler sind oder strengere Compliance-Anforderungen haben, kann die Trennung nach Schema (oder sogar nach Datenbank) die Blast-Radius reduzieren. Der Nachteil ist erhöhter Betriebsaufwand.
Sichere Voreinstellungen: Deny-by-default und Least Privilege
Gestalte Berechtigungen so, dass die Voreinstellung „kein Zugriff“ ist:
- Anwendungsrollen sollten nur minimale Tabellenrechte haben.\n- Admin-Workflows sollten separate Accounts und geprüfte Erhöhungen nutzen.\n- Vermeide gemeinsame "Superuser"-Verbindungen im Anwendungs-Code.
Diese Kontrollen funktionieren am besten gemeinsam: starkes Mandanten-Scoping, datenbankseitig erzwungene Policies wo möglich, und konservative Rechte, die Schaden begrenzen, wenn doch etwas schiefgeht.
Verschlüsselung und Key-Management in geteilten Datenspeichern
Verschlüsselung ist eine der wenigen Kontrollen, die auch dann helfen, wenn andere Isolationsschichten versagen. In einem geteilten Datenspeicher geht es darum, Daten zu schützen, während sie sich bewegen, während sie ruhen, und während deine Anwendung nachweist, für welchen Mandanten sie handelt.
Verschlüsselung in Transit und At-Rest
Für Daten in Transit erfordere TLS für jede Verbindungsstrecke: Client → API, API → Datenbank und alle internen Service-Aufrufe. Erzwinge TLS möglichst auf Datenbankebene (z. B. Ablehnung von Nicht-TLS-Verbindungen), damit „temporäre Ausnahmen“ nicht stillschweigend permanent werden.
Für Daten At-Rest nutze Datenbank- oder Storage-Verschlüsselung (managed disk encryption, TDE, verschlüsselte Backups). Das schützt vor verlorenen Medien, Snapshot-Exposure und bestimmten Infrastrukturkompromittierungen — aber es stoppt keine fehlerhafte Abfrage, die fremde Zeilen zurückliefert.
Geteilte Schlüssel vs. mandantenspezifische Schlüssel
Ein einzelner geteilter Verschlüsselungsschlüssel ist einfacher zu betreiben (weniger Schlüssel zu rotieren, weniger Fehlerquellen). Der Nachteil ist der Blast-Radius: wenn dieser Schlüssel offengelegt wird, sind alle Mandanten betroffen.
Mandantenspezifische Schlüssel reduzieren den Blast-Radius und helfen bei Kundenanforderungen (einige Unternehmen wollen mandantenspezifische Schlüsselkontrolle). Der Kompromiss ist Komplexität: Lifecycle-Management, Rotationspläne und Support-Workflows (z. B. was passiert, wenn ein Mandant seinen Schlüssel deaktiviert).
Ein praktischer Mittelweg ist Envelope-Verschlüsselung: ein Master-Key verschlüsselt mandantenspezifische Datenkeys und hält Rotation handhabbar.
Secrets-Management für Datenbank-Zugangsdaten
Speichere Datenbank-Zugangsdaten in einem Secrets-Manager, nicht in Umgebungsvariablen in Langzeitkonfigurationen. Bevorzuge kurzlebige Anmeldeinformationen oder automatische Rotation, und scope Zugriff nach Service-Rolle, sodass eine Kompromittierung eines Komponenten nicht automatisch jede Datenbank erreicht.
Token- und Session-Handling: Verhindern gefälschter Mandantenkontexte
Behandle Mandantenidentität als sicherheitskritisch. Akzeptiere niemals eine rohe Mandanten-ID vom Client als „Wahrheit“. Binde Mandantenkontext an signierte Token und serverseitige Autorisierungsprüfungen und validiere ihn bei jeder Anfrage, bevor du Datenbankaufrufe machst.
Auditierung, Monitoring und Incident-Readiness
Mehrmandantigkeit verändert, wie „normal“ aussieht. Du beobachtest nicht nur eine Datenbank — du beobachtest viele Mandanten in einem gemeinsamen System, in dem ein Fehler zu Cross-Mandanten-Exposition führen kann. Gute Auditierbarkeit und Monitoring reduzieren sowohl die Wahrscheinlichkeit als auch die Ausbreitung von Vorfällen.
Audit-Logs: die ganze Geschichte aufzeichnen
Mindestens solltest du jede Aktion loggen, die Mandantendaten lesen, ändern oder Zugriffsrechte vergeben kann. Die nützlichsten Audit-Events beantworten:
- Wer: Benutzer/Service-Identität, Auth-Methode, Rolle, Quell-IP/Gerät\n- Was: Operation (SELECT/UPDATE/DELETE), betroffene Objekte, Query-Klasse (nicht zwingend volles SQL), Before/After für privilegierte Änderungen\n- Wann: Zeitstempel mit Zeitzone, Request/Trace-ID zur Korrelation\n- Mandant: Mandanten-ID als eigenständiges Feld (niemals rückwirkend ableiten)
Logge auch administrative Aktionen: Anlegen von Mandanten, Ändern von Isolationspolicies, Modifizieren von RLS-Regeln, Rotieren von Schlüsseln und Ändern von Verbindungs-Strings.
Alerting für Cross-Mandanten- und Privilegien-Anomalien
Monitoring sollte Muster erkennen, die in gesundem SaaS-Verhalten unwahrscheinlich sind:
- Abfragen, die Zeilen für mehrere
tenant_ids zurückgeben, oder plötzliche Anstiege bei "tenant mismatch"-Rejections\n- Zugriff eines Service-Accounts auf Mandanten, die er normalerweise nicht berührt\n- Rasche Rollen-/Berechtigungsänderungen, neue Admins, deaktivierte Security-Policies oder RLS-Bypass-Versuche
Verknüpfe Alerts mit ausführbaren Runbooks: was zu prüfen ist, wie einzudämmen ist und wen zu alarmieren.
Admin-Kontrollen und Break-Glass-Prozeduren
Behandle privilegierten Zugriff wie eine Produktionsänderung. Nutze Least-Privilege-Rollen, kurzlebige Anmeldeinformationen und Genehmigungen für sensible Operationen (Schema-Änderungen, Datenexporte, Policy-Edits). Für Notfälle behalte ein Break-Glass-Konto, das streng kontrolliert wird: separate Zugangsdaten, verpflichtendes Ticket/Approval, zeitlich begrenzter Zugriff und zusätzliche Protokollierung.
Aufbewahrung und mandantengebundener Logzugriff
Setze Retention basierend auf Compliance- und Untersuchungsbedürfnissen, scopiere aber Log-Zugriffe so, dass Support-Mitarbeitende eines Mandanten nur Logs dieses Mandanten sehen. Wenn Kunden Audit-Exporte anfordern, liefere mandantengefilterte Berichte statt roher geteilter Logs.
Performance-Grundlagen und das Noisy-Neighbor-Problem
Mehrmandantigkeit erhöht Effizienz, weil viele Kunden dieselbe Datenbank-Infrastruktur teilen. Der Kompromiss ist, dass Performance ebenfalls eine geteilte Erfahrung wird: was ein Mandant tut, kann andere beeinflussen, selbst wenn ihre Daten sauber isoliert sind.
Das Noisy-Neighbor-Problem (in einfachen Worten)
Ein "noisy neighbor" ist ein Mandant, dessen Aktivität so hoch (oder so spitz) ist, dass er mehr als seinen fairen Anteil gemeinsamer Ressourcen verbraucht. Die Datenbank ist nicht "kaputt" — sie ist nur damit beschäftigt, diese Last zu verarbeiten, sodass andere Mandanten länger warten.
Stell es dir vor wie den Wasserdruck in einem Wohnhaus: eine Einheit betreibt mehrere Duschen und die Waschmaschine gleichzeitig, und alle anderen merken den geringeren Druck.
Was wird tatsächlich geteilt?
Selbst wenn Mandanten separate Zeilen oder Schemata haben, sind viele performancekritische Komponenten geteilt:
- CPU: Query-Execution, Sorts, Joins, Verschlüsselung/Entschlüsselung, Hintergrundwartung.\n- Speicher: Buffer/Cache-Seiten, Query-Arbeitspeicher, interne Queues.\n- Disk / I/O: Lesen von Datenfiles, Schreiben von Logs, Checkpoint-Flushes, Kompaktierung/Vacuum.\n- Verbindungen: DB-Verbindungslimits und Thread-Pools.\n- Caches: Plan-Cache, Buffer-Cache und teilweise Applikationscaches.
Wenn diese geteilten Pools gesättigt sind, steigt die Latenz für alle.
Warum bursty Workloads andere Mandanten stören
Viele SaaS-Workloads kommen in Bursts: ein Import, Monatsberichte, eine Marketingkampagne, ein Cron-Job zur vollen Stunde.
Bursts können "Staus" in der Datenbank erzeugen:
- Ein einzelner Mandant startet viele teure Queries gleichzeitig und drückt die CPU auf 100 %.\n- Große Writes verursachen zusätzlichen I/O (Log-Writes, Indexpflege), verlangsamen Reads für andere.\n- Verbindungs-Spikes füllen den Pool, sodass andere Mandanten keine Verbindung erhalten.
Auch wenn der Burst nur Minuten dauert, kann es zu Nachwirkungen kommen, während die Queues sich leeren.
Was Benutzer typischerweise bemerken
Aus Kundensicht wirken Noisy-Neighbor-Probleme zufällig und unfair. Typische Symptome:
- Timeouts beim Login, der Suche, Checkout oder Report-Generierung\n- Langsame Seiten, die zuvor schnell waren, besonders Listen und Dashboards\n- Inkonsistente Geschwindigkeit (schnell um 10:05, langsam um 10:10, wieder schnell um 10:20)\n- Hintergrundjobs verzögert (Exporte dauern länger, Webhooks verzögert)
Diese Symptome sind frühe Warnzeichen, dass Performance-Isolationstechniken (weiter unten) nötig sind, nicht nur "mehr Hardware".
Techniken zur Ressourcenisolation und Drosselung
Mehrmandantigkeit funktioniert am besten, wenn ein Kunde nicht mehr als seinen fairen Anteil an DB-Kapazität "ausleihen" kann. Ressourcenisolation sind Guardrails, die verhindern, dass ein schwerer Mandant alle anderen verlangsamt.
Connection-Pooling-Limits und pro-Mandant-Quoten
Ein häufiger Fehler ist unbeschränkte Verbindungen: ein Mandanten-Traffic-Spike öffnet hunderte Sessions und verdirbt der DB die Ressourcen.
Setze harte Limits an zwei Stellen:
- Im Application-Pool: max connections pro Service-Instanz begrenzen und ein Minimum für Hintergrundjobs reservieren.\n- Pro Mandant: Quoten wie "N gleichzeitige Requests" oder "M gleichzeitige DB-Sessions" einführen, abgeleitet vom Mandanten-Plan.
Auch wenn die Datenbank kein direktes "Connections per tenant" erzwingen kann, kannst du es approximieren, indem du jeden Mandanten durch einen dedizierten Pool oder Pool-Partition leitest.
Rate-Limiting und Workload-Shaping (App + DB)
Rate-Limiting sorgt für Fairness über die Zeit. Setze es nah an der Peripherie (API-Gateway/App) und, wo unterstützt, in der Datenbank (Resource-Groups/Workload-Management).
Beispiele:
- Token-Bucket-Limits pro Mandant für teure Endpunkte (Exporte, Suche)\n- Prioritätsstufen, sodass interaktive Requests Batch-Workloads schlagen\n- Queue-basiertes Shaping, um Bursts zu glätten statt sie direkt in die DB zu drücken
Query-Timeouts, Statement-Limits und Circuit-Breaker
Schütze die Datenbank vor "ausgeuferten" Abfragen:
- Query-/Statement-Timeouts zum Stoppen langer Scans\n- Maximale zurückgegebene Reihen/Bytes für Endpunkte, die Ergebnisgrößen explodieren lassen können\n- Circuit-Breaker, die ein teures Feature temporär blockieren, wenn Error-Raten oder Latenz Grenzwerte überschreiten
Diese Controls sollten sauber fehlschlagen: eine klare Fehlermeldung zurückgeben und Retry/Backoff vorschlagen.
Read-Replicas und Caching zur Reduzierung von Contention
Verlagere read-lastigen Traffic weg vom Primary:
- Read-Replicas für Dashboards, Reporting und Analytics-Queries\n- Caching (mandantenspezifische Keys, kurze TTLs) für wiederholte Lookups und Konfigurationsdaten
Das Ziel ist nicht nur Geschwindigkeit — sondern auch weniger Lock-Pressure und CPU-Contention, damit Noisy-Mandanten weniger Einfluss haben.
Datenmodellentscheidungen, die die Geschwindigkeit beeinflussen
Performance-Probleme in Mehrmandanten-Setups sehen oft aus wie "die DB ist langsam", die Ursache ist aber meist das Datenmodell: wie Mandantendaten indiziert, gefiltert, indiziert und physisch angeordnet sind. Gutes Modeling macht mandantengebundene Abfragen natürlich schnell; schlechtes Modeling zwingt die DB zu viel Arbeit.
Indexierung für mandantengebundene Queries
Die meisten SaaS-Abfragen sollten eine Mandantenkennung enthalten. Modelle das explizit (z. B. tenant_id) und entwirf Indizes, die damit beginnen. In der Praxis ist ein zusammengesetzter Index wie (tenant_id, created_at) oder (tenant_id, status) viel nützlicher als nur created_at oder status zu indexieren.
Das gilt auch für Einzigartigkeiten: wenn E-Mails nur pro Mandant einzigartig sind, erzwinge das mit (tenant_id, email) statt eines globalen email-Constraints.
Full-Table-Scans vermeiden (fehlende Mandantenfilter)
Ein häufiges Muster für langsame Queries ist ein versehentlicher Cross-Mandanten-Scan: eine Abfrage vergisst den Mandantenfilter und liest einen großen Tabellenbereich.
Mache den sicheren Pfad einfach:
- Erzwinge Mandantenfilter in deiner Abfrage-Schicht (ORM-Scopes, Repository-Methoden)\n- Nutze Datenbankschutz, wo verfügbar (z. B. Default-Views oder Policies), damit ungetaggter Zugriff schnell fehlschlägt
Partitionierung und Sharding: nach Mandant oder Zeit
Partitionierung kann die Datenmenge reduzieren, die jede Abfrage betrachten muss. Partitioniere nach Mandant, wenn Mandanten groß und ungleich verteilt sind. Partitioniere nach Zeit, wenn der Zugriff überwiegend aktuell ist (Events, Logs, Rechnungen), oft mit tenant_id als führendem Index innerhalb jeder Partition.
Sharding ist eine Option, wenn eine einzelne Datenbank den Peak-Durchsatz nicht schafft oder wenn ein Mandant die Ressourcen aller anderen bedroht.
Hot-Mandanten managen
"Hot-Mandanten" zeigen sich durch disproportionalen Lese-/Schreib-Volumen, Lock-Contention oder übergroße Indizes.
Erkenne sie durch Tracking von mandantenspezifischer Query-Zeit, gelesenen Zeilen und Schreibraten. Bei Dominanz isoliere sie: Umzug in ein eigenes Shard/DB, Aufsplitten großer Tabellen pro Mandant oder dedizierte Caches und Rate-Limits einführen, sodass andere Mandanten ihre Performance behalten.
Operative Praktiken, die sowohl Sicherheit als auch Performance schützen
Mehrmandantigkeit scheitert selten, weil die Datenbank „es nicht kann“. Sie scheitert, wenn tägliche Abläufe kleine Inkonsistenzen zulassen, die sich zu Sicherheitslücken oder Performance-Regressionen auswachsen. Ziel ist, dass der sichere Weg die Default-Option für jede Änderung, jeden Job und jedes Deploy ist.
Standardisiere den Mandantenschlüssel (und setze ihn überall durch)
Wähle einen einzigen, kanonischen Mandanten-Identifier (z. B. tenant_id) und verwende ihn konsistent in Tabellen, Indizes, Logs und APIs. Konsistenz reduziert Sicherheitsfehler (falschen Mandanten abfragen) und Performance-Überraschungen (fehlende passende Composite-Indizes).
Praktische Safeguards:
- Fordere
tenant_idin allen primären Zugriffspfaden (Queries, Repositories, ORM-Scopes)\n- Füge Composite-Indizes hinzu, die mittenant_idbeginnen für gängige Lookups\n- Bevorzuge Datenbank-Constraints (Foreign Keys, Check-Constraints), um fehlerhafte Writes früh zu erkennen
Gegen Mandantenverwechslungen in Hintergrundarbeit schützen
Async-Worker sind eine häufige Fehlerquelle, weil sie "out of band" vom Request laufen, der den Mandantenkontext gesetzt hat.
Operative Muster, die helfen:
- Übergib
tenant_idexplizit in jedem Job-Payload; verlasse dich nicht auf ambienten Kontext\n- Füge den Mandantenschlüssel in Idempotency-Keys und Cache-Keys ein\n- Loggetenant_idbei Job-Start/Ende und bei jedem Retry, damit Untersuchungen schnell scoped werden können
Migrationen mandantensicher gestalten
Schema- und Datenmigrationen sollten ohne perfekte, synchrone Rollouts einsetzbar sein.
Nutze Rolling-Änderungen:
- Expand/Contract-Strategie (neue Spalte/Index hinzufügen, dual-write/read, dann alte Pfade entfernen)\n- Vermeide lange blockierende Operationen; batch Backfills nach Mandant um Last zu steuern\n- Stelle sicher, dass Backfill-Queries mandantengebunden und rate-limitiert sind, um selbst verursachte Noisy-Neighbor-Effekte zu vermeiden
Isolationstests, nicht nur Happy-Path-Tests
Füge automatisierte Negative-Tests hinzu, die absichtlich versuchen, auf fremde Mandantendaten zuzugreifen (lesen und schreiben). Behandle diese Tests als Release-Blocker.
Beispiele:
- Versuche, einen bekannten Datensatz von Mandant A abzurufen, während du als Mandant B authentifiziert bist\n- Führe Hintergrundjob-Tests mit falscher
tenant_idaus und verifiziere harte Fehler\n- Regressions-Tests für jeden Query-Helper, um sicherzustellen, dass Mandanten-Scoping immer angewendet wird
Backups, Restores und mandantenbezogene Datenoperationen
Backups sind leicht zu beschreiben ("kopiere die Datenbank") und überraschend schwer sicher auszuführen in einem Mehrmandanten-Setup. Sobald viele Kunden Tabellen teilen, brauchst du einen Plan, wie du einen Mandanten wiederherstellst, ohne andere zu exponieren oder zu überschreiben.
Backup/Restore-Strategien: ein Mandant vs. alle
Ein Full-Database-Backup bleibt die Grundlage für Disaster Recovery, aber es reicht nicht für alltägliche Supportfälle. Gängige Ansätze:
- Full Backups + Point-in-Time Recovery für Vorfälle, die alle betreffen (Korruption, Regionen-Ausfall)\n- Mandantenspezifische Exporte (logische Dumps gefiltert nach
tenant_id) um die Daten eines einzelnen Mandanten wiederherzustellen\n- Separater Speicher pro Mandant (sofern machbar), damit Restores natürlich mandantenbegrenzt sind
Wenn du auf logische Exporte setzt, behandle den Exportjob wie Produktionscode: er muss Mandantenisolation erzwingen (z. B. über RLS) statt sich auf eine einmal geschriebene WHERE-Klausel zu verlassen.
Mandanten-spezifischer Export/Löschen (Datenschutzanfragen)
Datenschutzanfragen (Export, Löschung) sind mandantenbezogene Operationen, die Sicherheit und Performance berühren. Baue wiederholbare, geprüfte Workflows für:
- Export von Mandantendaten in konsistenten Snapshots\n- Löschen von Mandantendaten ohne verwaiste Zeilen zu hinterlassen\n- Nachweis der Fertigstellung durch Logs und Checksummen
Verhindern versehentlicher Cross-Mandant-Restores
Das größte Risiko ist nicht ein Hacker — es ist ein gehetzter Operator. Reduziere menschliche Fehler mit Guardrails:
- Fordere eine Mandantenkennung plus eine sekundäre Bestätigung (Mandantenname, Billing-ID)\n- Validate Row-Counts und
tenant_id-Distribution vor dem Import\n- Restore zuerst in einer Quarantäneumgebung, dann promote
DR-Übungen und Überprüfen der Grenzen danach
Nach einem Disaster-Recovery-Drill hör nicht beim "die App ist wieder da" auf. Führe automatisierte Prüfungen durch, die Mandantenisolation bestätigen: Stichproben-Abfragen über Mandanten, Audit-Log-Review und stichprobenartige Verifikation, dass Verschlüsselungsschlüssel und Zugriffsrollen weiterhin korrekt gefiltert sind.
Wann Mehrmandantigkeit nicht mehr passt
Mehrmandantigkeit ist oft die beste Default-Option für SaaS, aber sie ist keine permanente Entscheidung. Wenn Produkt und Kundenmix sich entwickeln, kann das "eine geteilte Datenspeicher"-Modell Geschäftsrisiken erzeugen oder die Auslieferung verlangsamen.
Signale, dass du Isolation erhöhen solltest
Erhöhe die Isolation, wenn immer wieder eines oder mehrere dieser Zeichen auftreten:
- Wachstums- und Skalierungseffekte: wenige Mandanten verursachen unverhältnismäßig viel Traffic, Speicher oder Hintergrundjobs, und Optimierungen für alle werden schwerer\n- Compliance-/Vertragsanforderungen: Kunden verlangen dedizierte Umgebungen, bestimmte Residency-Kontrollen, Mandanten-eigene Schlüssel oder striktere Audit-Grenzen als dein Shared-Modell sauber bieten kann\n- Schwere Mandanten mit speziellen Mustern: große Importe, Reporting-Bursts oder kundenspezifische Integrationen erzeugen wiederkehrende Contention, die sich nicht mit Tuning und Throttles lösen lässt
Hybride Modelle, die Kosten vernünftig halten
Du musst nicht zwischen "alles geteilt" und "alles dediziert" wählen. Gängige Hybride:
- Ein paar Top-Tenants auslagern in separate Datenbanken/Cluster, während die lange Tail im Shared-Betrieb bleibt\n- Gestufte Angebote: Shared per Default, isoliert für Enterprise-Pläne\n- Funktionale Isolation: transaktionale Workloads geteilt halten, aber Analytics/Reporting für schwere Mandanten in separate Stores verschieben
Kosten und Komplexität gegenüber Stakeholdern erklären
Mehr Isolation bedeutet meist höhere Infrastrukturkosten, mehr operativen Aufwand (Migrationen, Monitoring, On-Call) und mehr Release-Koordination (Schema-Änderungen über mehrere Umgebungen). Der Vorteil sind klarere Performance-Garantien und einfachere Compliance-Gespräche.
Nächste Schritte
Wenn du Isolationsoptionen evaluierst, sieh dir verwandte Guides in /blog an oder vergleiche Pläne und Bereitstellungsoptionen auf /pricing.
Wenn du ein SaaS schnell prototypen und Mehrmandanten-Annahmen früh testen willst (Mandanten-Scoping, RLS-freundliche Schemata, Throttling und operative Workflows), kann eine Vibe-Coding-Plattform wie Koder.ai helfen: damit lässt sich eine funktionierende React + Go + PostgreSQL App aus Chat hochziehen, im Planungsmodus iterieren und mit Snapshots und Rollback deployen — und später den Quellcode exportieren, wenn du die Architektur für Produktion härten willst.
FAQ
Was ist eine Mehrmandanten-Datenbank einfach erklärt?
Eine Mehrmandanten-Datenbank ist eine Architektur, bei der mehrere Kunden dieselbe Datenbank-Infrastruktur (oft auch dasselbe Schema) teilen, während Anwendung und/oder Datenbank sicherstellen, dass jeder Mandant nur auf seine eigenen Daten zugreifen kann. Die Kernanforderung ist eine strikte Mandantenausgrenzung bei jedem Lese- und Schreibvorgang.
Warum entscheiden sich SaaS-Teams für Mehrmandanten-Systeme?
Mehrmandanten-Architekturen werden oft gewählt wegen:
- Geringerer Kosten pro Kunde (gemeinsame Rechen- und Speicherressourcen, Lizenzen)
- Einfacherer Betrieb in großem Maßstab (weniger Datenbanken zu patchen, upzugraden und zu überwachen)
- Schnelleres Onboarding (kein vollständiges Datenbank-Stack-Provisioning für jeden Kunden)
Der Kompromiss ist, dass Sie bewusst Isolation und Performance-Schutzmaßnahmen bauen müssen.
Was sind die wichtigsten Mehrmandanten-Datenbank-Modelle?
Gängige Modelle (von stärkerer Isolation zu stärkerem Teilen) sind:
- Datenbank-pro-Mandant: stärkste Isolationsgrenze, hoher Betriebsaufwand.
- Schema-pro-Mandant: gute Trennung, dennoch repetitive Migrationen.
- Tabelle-pro-Mandant: funktioniert kurzfristig, skaliert oft schlecht.
- Geteilte Tabellen (tenant_id-Spalte): einfachere Operationen, am schwersten abzusichern und zu optimieren.
Ihre Wahl bestimmt die Isolationsgrenze und den operativen Aufwand.
Wie verändert Mehrmandantenbetrieb das Sicherheitsbedrohungsmodell?
Das größte Risiko verschiebt sich hin zu Cross-Mandanten-Zugriffen, die durch Routinefehler passieren, nicht nur durch externe Angreifer. Mandantenkontext (z. B. tenant_id) muss als Autorisationserfordernis behandelt werden, nicht als optionaler Filter. Sie müssen außerdem Produktionsrealitäten wie Konkurrenz, Caches, Retries und Hintergrundjobs berücksichtigen.
Was verursacht typischerweise Datenlecks zwischen Mandanten?
Die häufigsten Ursachen sind:
- Fehlende Mandantenfilter in einem Pfad
- Joins, bei denen eine Tabelle scoped ist, die verbundene Tabelle aber nicht
- Caches, die nach URL/Benutzer, aber nicht nach Mandant gekeyt sind
- Prepared Statements, die fälschlich die falsche
tenant_idbinden - Hintergrundjobs, die den Mandantenkontext verlieren
Bauen Sie Guardrails, damit ungetaggte Abfragen schwer (oder unmöglich) ausführbar sind.
Wann sollte man Row-Level Security (RLS) einsetzen und wovor schützt sie?
Row-Level Security (RLS) verschiebt Mandantenprüfungen in die Datenbank und verwendet Policies, die SELECT/UPDATE/DELETE auf Zeilen beschränken, die zum aktuellen Mandanten passen. RLS reduziert die Abhängigkeit davon, dass Entwickler immer die WHERE-Klausel richtig setzen, sollte aber mit App-seitiger Scoping-Logik, Least-Privilege-Prinzipien und starker Testabdeckung kombiniert werden. Betrachte RLS als zusätzliche Sperre, nicht als einzige.
Was sind die wichtigsten Isolationskontrollen, um Cross-Mandant-Zugriff zu verhindern?
Eine praktische Basis umfasst:
- Eine kanonische
tenant_idin mandantenbesitzten Tabellen - Komposite Unique- und Foreign-Key-Constraints, die
tenant_ideinbeziehen - Deny-by-default-Berechtigungen und DB-Rollen mit minimalen Rechten
- Getrennte, geprüfte Admin-Zugänge (vermeide Superuser-Verbindungen in App-Code)
- Negative Tests, die Cross-Mandant-Lese-/Schreibzugriffe versuchen
Ziel ist, dass Fehler sicher fehlschlagen.
Wie funktionieren Verschlüsselung und Key-Management in einem geteilten Datenspeicher?
Verschlüsselung hilft, deckt aber andere Risiken ab:
- In Transit (TLS): schützt Daten zwischen Diensten.
- At Rest: schützt Snapshots/Disks/Backups, aber nicht fehlerhafte Abfragen.
- Mandanten-spezifische Schlüssel verringern die Blast-Radius, erhöhen aber die Betriebs-Komplexität.
Behandle Mandantenidentität als sicherheitskritisch: vertraue nicht einer rohen Mandanten-ID vom Client; binde sie an signierte Tokens und serverseitige Prüfungen.
Was ist das Noisy-Neighbor-Problem und wie mildert man es?
Noisy-Neighbor-Probleme entstehen, wenn ein Mandant so viele gemeinsame Ressourcen (CPU, Speicher, I/O, Verbindungen) verbraucht, dass die Latenz für alle steigt. Praktische Gegenmaßnahmen sind:
- Harte Verbindungspool-Limits (und pro-Mandant-Quoten, wo möglich)
- Rate-Limiting und Workload-Shaping für teure Endpunkte
- Query-Timeouts, Max-Rows/Bytes und Circuit-Breaker
- Read-Replicas und mandantenspezifische Cache-Keys
Ziel ist Fairness, nicht nur maximale Durchsatzwerte.
Wann sollte man weg von voller Mehrmandanten-Nutzung gehen und welche Hybridoptionen gibt es?
Erhöhe Isolation, wenn Sie regelmäßig sehen:
- Wenige Mandanten dominieren Traffic/Storage und verursachen Engpässe
- Compliance-Anforderungen verlangen dedizierte Umgebungen, Residency oder Key-Control
- Workloads, die sich mit Throttles/Tuning nicht einfangen lassen
Gängige Hybrid-Optionen: Auslagerung einiger Top-Tenants in eigene DB/Cluster, gestufte Pläne (shared vs. dedicated) oder Trennung von Analytics/Reporting für schwere Mandanten.