Multi Tenancy Datenmodelle im Vergleich
AI generated
SELECT
JOIN
SQL · Datenmodellierung · Multi Tenancy
Multi Tenancy Datenmodelle im Vergleich
Shared Schema, Schema-per-Tenant, Database-per-Tenant

Multi Tenancy entscheidet, ob eine SaaS-Anwendung Daten hunderter Mandanten sicher trennt oder eines Tages einen Datenabfluss zwischen Kunden riskiert. Dieser Beitrag vergleicht Shared Schema mit tenant_id, Schema-per-Tenant und Database-per-Tenant nach Isolation, Migrationsaufwand und Ressourcen-Isolation, damit die Entscheidung auf echten Kriterien statt auf Bauchgefuehl basiert.

18 Min. Lesezeit Row Level Security · tenant_id · Schema-Isolation PostgreSQL · MySQL

1. Was Multi Tenancy bedeutet und welche Fragen das Datenmodell beantworten muss

Multi Tenancy beschreibt eine Softwarearchitektur, bei der eine einzige Anwendungsinstanz Daten mehrerer voneinander unabhaengiger Kunden, sogenannter Mandanten oder Tenants, gleichzeitig verwaltet. Jeder Mandant erwartet dabei, dass seine Daten von denen anderer Mandanten vollstaendig isoliert bleiben, obwohl sie technisch moeglicherweise dieselbe Datenbank, dieselben Tabellen oder sogar dieselben Zeilen teilen.

Das Datenmodell hinter Multi Tenancy muss drei zentrale Fragen beantworten: Wie wird verhindert, dass ein Mandant versehentlich oder absichtlich Daten eines anderen Mandanten sieht? Wie werden Schema-Aenderungen und Migrationen ausgerollt, wenn hunderte oder tausende Mandanten gleichzeitig betroffen sind? Und wie wird verhindert, dass ein einzelner Mandant mit ungewoehnlich hoher Last die Performance fuer alle anderen beeintraechtigt? Die Antwort auf diese drei Fragen unterscheidet sich fundamental je nach gewaehltem Modell.

In der Praxis existieren drei etablierte Grundmodelle fuer Multi Tenancy: Shared Database mit Shared Schema, bei dem alle Mandanten dieselben Tabellen nutzen und eine Spalte den Mandanten markiert, Schema-per-Tenant, bei dem jeder Mandant ein eigenes Datenbankschema innerhalb derselben Datenbankinstanz erhaelt, und Database-per-Tenant, bei dem jeder Mandant eine vollstaendig eigene Datenbank bekommt. Die folgenden Abschnitte gehen jedes Modell im Detail durch.

2. Modell 1: Shared Database, Shared Schema mit tenant_id

Im verbreitetsten Modell fuer Multi Tenancy teilen sich alle Mandanten dieselben Tabellen in derselben Datenbank. Jede mandantenspezifische Tabelle bekommt eine zusaetzliche Spalte tenant_id, die jede Zeile eindeutig einem Mandanten zuordnet. Jede Abfrage muss diese Spalte in der WHERE-Bedingung beruecksichtigen, entweder explizit im Anwendungscode oder ueber einen automatischen Scope im ORM.


-- Shared Schema: tenant_id als Pflichtspalte in jeder mandantenspezifischen Tabelle
CREATE TABLE invoices (
  invoice_id   SERIAL PRIMARY KEY,
  tenant_id    INTEGER NOT NULL REFERENCES tenants(tenant_id),
  customer_id  INTEGER NOT NULL,
  amount       NUMERIC(10,2) NOT NULL,
  created_at   TIMESTAMPTZ NOT NULL DEFAULT now()
);

-- Zusammengesetzter Index: tenant_id fuehrend, damit jede Abfrage
-- effizient auf den eigenen Mandanten eingegrenzt werden kann
CREATE INDEX idx_invoices_tenant_customer
  ON invoices (tenant_id, customer_id);

-- Jede Abfrage MUSS tenant_id filtern
SELECT * FROM invoices
WHERE tenant_id = 42 AND customer_id = 1001;

Der Vorteil dieses Modells liegt in seiner Einfachheit fuer Betrieb und Migrationen: Ein einziges Schema, eine einzige Migration, die fuer alle Mandanten gleichzeitig gilt. Ressourcen wie Connection-Pools und Backups werden nur einmal verwaltet, was Infrastrukturkosten bei vielen kleinen Mandanten niedrig haelt. Der grosse Nachteil ist das Risiko menschlichen Fehlers: Eine einzige vergessene tenant_id-Bedingung in einer neuen Abfrage kann Daten eines Mandanten fuer einen anderen sichtbar machen, ein Fehler, der bei Multi Tenancy besonders schwer wiegt.

3. Row Level Security als Absicherung fuer Shared Schema

Um das Risiko einer vergessenen tenant_id-Bedingung zu entschaerfen, bieten PostgreSQL und einige andere Datenbanken Row Level Security (RLS) an: Eine Policy auf Datenbankebene filtert automatisch jede Abfrage nach dem aktuell aktiven Mandanten, unabhaengig davon, ob der Anwendungscode selbst daran gedacht hat. Damit wird die Isolation nicht mehr allein dem Anwendungscode ueberlassen, sondern zusaetzlich von der Datenbank erzwungen.


-- Row Level Security aktivieren und Policy definieren
ALTER TABLE invoices ENABLE ROW LEVEL SECURITY;

CREATE POLICY tenant_isolation ON invoices
  USING (tenant_id = current_setting('app.current_tenant')::int);

-- Anwendung setzt den aktiven Mandanten zu Beginn jeder Session/Transaktion
SET app.current_tenant = '42';

-- Diese Abfrage sieht automatisch NUR Zeilen mit tenant_id = 42,
-- auch wenn die WHERE-Klausel selbst keine tenant_id-Bedingung enthaelt
SELECT * FROM invoices WHERE customer_id = 1001;

-- Selbst ein Entwickler-Fehler ohne explizite tenant_id-Bedingung
-- kann keine fremden Mandantendaten mehr zurueckgeben

Row Level Security ist damit eine zweite Verteidigungslinie, die selbst dann greift, wenn Anwendungscode fehlerhaft ist. Der Nachteil ist zusaetzliche Betriebskomplexitaet: Jede Datenbankverbindung muss zuverlaessig den korrekten Mandantenkontext setzen, bevor sie Abfragen ausfuehrt, und Connection-Pooling-Loesungen muessen darauf achten, dass eine wiederverwendete Verbindung nicht versehentlich den Mandantenkontext einer fruehen Session behaelt.

4. Modell 2: Shared Database, Schema-per-Tenant

Das zweite Modell haelt weiterhin alle Mandanten in derselben physischen Datenbankinstanz, gibt aber jedem Mandanten ein eigenes Datenbankschema mit identischer Tabellenstruktur. Die Anwendung wechselt beim Verbindungsaufbau den search_path beziehungsweise das aktive Schema, sodass identische SQL-Anweisungen ohne tenant_id-Filter automatisch nur die Tabellen des jeweiligen Mandanten treffen.


-- Ein Schema pro Mandant, identische Tabellenstruktur in jedem
CREATE SCHEMA tenant_42;
CREATE SCHEMA tenant_43;

CREATE TABLE tenant_42.invoices (
  invoice_id   SERIAL PRIMARY KEY,
  customer_id  INTEGER NOT NULL,
  amount       NUMERIC(10,2) NOT NULL
);

-- Anwendung wechselt beim Verbindungsaufbau den search_path
SET search_path TO tenant_42;

-- Dieselbe Abfrage wie bei Shared Schema, aber OHNE tenant_id-Spalte,
-- weil die Trennung ueber das Schema selbst erfolgt
SELECT * FROM invoices WHERE customer_id = 1001;

Der Vorteil dieses Modells ist strukturelle Isolation auf Datenbankebene, ohne fuer jeden Mandanten eine eigene Datenbankinstanz betreiben zu muessen. Ein Mandant kann seine Daten technisch nicht versehentlich sehen, ausser der search_path wird explizit falsch gesetzt. Der Nachteil zeigt sich bei sehr vielen Mandanten: Datenbanksysteme haben praktische Obergrenzen fuer die Anzahl paralleler Schemata, und Tools fuer Migrationen, Backups und Monitoring muessen mit hunderten oder tausenden Schemata umgehen koennen, was viele Standard-Tools nicht ohne Anpassung leisten.

5. Modell 3: Database-per-Tenant

Das dritte Modell geht einen Schritt weiter und gibt jedem Mandanten eine vollstaendig eigene Datenbank, oft sogar auf einer eigenen Datenbankinstanz oder einem eigenen Server. Die Anwendung haelt eine Zuordnungstabelle, die pro Mandant die Verbindungsinformationen zur richtigen Datenbank speichert, und routet jede eingehende Anfrage basierend auf dem Mandanten zur passenden Verbindung.


-- Zentrale Zuordnungstabelle in einer separaten "Control Plane"-Datenbank
CREATE TABLE tenant_routing (
  tenant_id     INTEGER PRIMARY KEY,
  db_host       VARCHAR(255) NOT NULL,
  db_name       VARCHAR(100) NOT NULL,
  db_port       INTEGER NOT NULL DEFAULT 5432
);

-- Pseudocode: Anwendung waehlt Connection basierend auf Mandant
-- SELECT db_host, db_name FROM tenant_routing WHERE tenant_id = 42;
-- connection = connectionPool.get(routingResult.db_host, routingResult.db_name);
-- connection.query("SELECT * FROM invoices WHERE customer_id = 1001");
-- Keine tenant_id-Spalte noetig, physische Trennung erledigt die Isolation

-- Migration muss pro Mandantendatenbank einzeln ausgefuehrt werden
-- fuer host, db in list_all_tenant_databases():
--     run_migration(host, db, "V42__add_discount_column.sql")

Der Vorteil ist maximale Isolation: Ein Datenlek zwischen Mandanten ist auf Datenbankebene praktisch ausgeschlossen, und einzelne Mandanten koennen sogar unterschiedliche Datenbank-Versionen, eigene Backup-Zeitfenster oder sogar geografisch getrennte Standorte fuer regulatorische Anforderungen bekommen. Der Preis ist erheblicher operativer Aufwand: Migrationen muessen ueber potenziell tausende einzelne Datenbanken ausgerollt werden, Monitoring und Kapazitaetsplanung skalieren linear mit der Mandantenzahl, und die Infrastrukturkosten steigen deutlich staerker als bei den beiden anderen Modellen.

6. Migrationen und Schema-Aenderungen bei tausenden Mandanten

Ein oft unterschaetzter Aspekt von Multi Tenancy ist der operative Aufwand fuer Schema-Migrationen. Bei Shared Schema ist eine Migration trivial: eine einzige ALTER TABLE-Anweisung betrifft automatisch alle Mandanten gleichzeitig. Bei Schema-per-Tenant und erst recht bei Database-per-Tenant muss dieselbe Migration mehrfach ausgefuehrt werden, einmal pro Schema oder Datenbank, was bei tausenden Mandanten zu Migrationslaeufen fuehrt, die Stunden dauern koennen und bei einem Fehler mitten im Rollout einen inkonsistenten Zwischenzustand hinterlassen.

Praktische Loesungen fuer dieses Problem sind Migrations-Orchestrierungs-Tools, die Migrationen in Batches parallelisieren, den Fortschritt pro Mandant persistieren und bei einem Fehler gezielt nur die betroffenen Mandanten erneut versuchen, statt den gesamten Lauf neu zu starten. Ein Canary-Ansatz, bei dem eine Migration zunaechst nur auf einer kleinen Teilmenge von Mandanten ausgefuehrt und ueberwacht wird, bevor der vollstaendige Rollout startet, reduziert das Risiko eines flaechendeckenden Fehlers erheblich.

7. Noisy-Neighbor-Probleme und Ressourcen-Isolation

Der sogenannte Noisy-Neighbor-Effekt beschreibt eine Situation, in der ein einzelner Mandant durch ungewoehnlich hohe Last, etwa einen ineffizienten Batch-Job oder einen unerwarteten Traffic-Spike, die Performance fuer alle anderen Mandanten auf derselben gemeinsamen Infrastruktur beeintraechtigt. Bei Shared Schema und Schema-per-Tenant teilen sich alle Mandanten dieselben Datenbank-Ressourcen wie CPU, Arbeitsspeicher und I/O, wodurch dieser Effekt strukturell moeglich ist.

Gegenmassnahmen reichen von Ressourcen-Limits pro Mandant auf Anwendungsebene, etwa Rate Limiting und Query-Timeouts, ueber Connection-Pool-Kontingente pro Mandant bis hin zu einer bewussten Segmentierung: Grosse oder besonders ressourcenhungrige Mandanten wandern in ein Database-per-Tenant-Modell, waehrend kleinere Mandanten weiterhin im guenstigeren Shared-Schema-Modell verbleiben. Diese hybride Strategie kombiniert die Kosteneffizienz von Shared Schema mit der Isolation von Database-per-Tenant genau dort, wo sie wirklich noetig ist.

8. Entscheidungskriterien: wann welches Modell

Die Wahl des richtigen Multi-Tenancy-Modells haengt von drei Faktoren ab: der erwarteten Anzahl an Mandanten, den Isolationsanforderungen durch Regulierung oder Kundenwunsch, und dem verfuegbaren Betriebsbudget fuer Infrastruktur und Migrations-Tooling. Ein Startup mit tausenden kleinen Mandanten und geringem Betriebsteam faehrt meist besser mit Shared Schema plus Row Level Security. Ein B2B-Anbieter mit wenigen, aber sehr grossen Enterprise-Kunden, die explizit dedizierte Infrastruktur verlangen, profitiert oft von Database-per-Tenant trotz hoeherer Kosten.

Schema-per-Tenant liegt oft dazwischen und eignet sich fuer mittelgrosse Mandantenzahlen mit moderaten Isolationsanforderungen, etwa wenn regulatorische Vorgaben eine physische Trennung von Tabellen verlangen, ohne gleich eine vollstaendig eigene Datenbank pro Mandant zu rechtfertigen. Wichtig ist, diese Entscheidung nicht als einmalig und unveraenderlich zu betrachten: Viele SaaS-Anbieter starten mit Shared Schema und migrieren einzelne, besonders anspruchsvolle Mandanten spaeter gezielt in ein isolierteres Modell.

9. Die drei Modelle im Vergleich

Die folgende Tabelle vergleicht die drei Modelle fuer Multi Tenancy nach Isolationsgrad, Migrationsaufwand und Infrastrukturkosten.

Modell Isolationsgrad Migrationsaufwand Infrastrukturkosten
Shared Schema + tenant_id Gering ohne RLS, mittel mit RLS Eine Migration fuer alle Niedrig
Schema-per-Tenant Hoch Pro Schema einzeln Mittel
Database-per-Tenant Sehr hoch Pro Datenbank einzeln Hoch

10. Zusammenfassung

Multi Tenancy ist keine einzelne Technik, sondern eine Bandbreite an Modellen mit unterschiedlichen Trade-offs zwischen Isolation, Kosten und Betriebsaufwand. Shared Schema mit tenant_id ist am guenstigsten und einfachsten zu migrieren, verlangt aber diszipliniertes Filtern in jeder Abfrage, das sich mit Row Level Security zusaetzlich absichern laesst. Schema-per-Tenant bietet strukturelle Isolation ohne die volle Kostenlast von Database-per-Tenant, stoesst aber bei sehr vielen Mandanten an praktische Grenzen.

Database-per-Tenant liefert maximale Isolation und Flexibilitaet fuer einzelne grosse Kunden, kostet aber deutlich mehr Infrastruktur und Migrations-Tooling. Die richtige Wahl haengt von Mandantenzahl, Isolationsanforderungen und Betriebsbudget ab, und viele erfolgreiche SaaS-Architekturen kombinieren mehrere Modelle je nach Mandantengroesse in einer hybriden Strategie.

Multi Tenancy Datenmodelle, das Wichtigste auf einen Blick

Shared Schema

Guenstigstes Modell, tenant_id in jeder Tabelle, Row Level Security als zweite Verteidigungslinie.

Schema-per-Tenant

Strukturelle Isolation ueber das Schema selbst, Migrationen muessen pro Schema wiederholt werden.

Database-per-Tenant

Maximale Isolation und Flexibilitaet, hoechste Infrastruktur- und Migrationskosten.

Noisy Neighbor

Rate Limiting, Connection-Pool-Kontingente und gezielte Segmentierung grosser Mandanten mindern den Effekt.

11. FAQ: Multi Tenancy Datenmodelle im Vergleich

1Was bedeutet Multi Tenancy?
Eine Anwendungsinstanz verwaltet Daten mehrerer unabhaengiger Mandanten gleichzeitig, mit vollstaendiger Isolation zwischen ihnen.
2Was ist das Shared-Schema-Modell?
Alle Mandanten teilen sich dieselben Tabellen, eine tenant_id-Spalte markiert die Zugehoerigkeit jeder Zeile.
3Was ist Row Level Security?
Eine Policy, die jede Abfrage automatisch nach dem aktiven Mandanten filtert, auch ohne explizite tenant_id-Bedingung im Code.
4Wie unterscheidet sich Schema-per-Tenant?
Jeder Mandant bekommt ein eigenes Schema statt gemeinsamer Tabellen mit tenant_id-Spalte.
5Wann lohnt sich Database-per-Tenant?
Bei wenigen grossen Kunden mit expliziten Anforderungen an physische Trennung oder eigene Standorte.
6Wie laufen Migrationen bei vielen Mandanten?
Bei Shared Schema einmalig, bei den anderen Modellen orchestriert ueber Batches pro Schema oder Datenbank.
7Was ist der Noisy-Neighbor-Effekt?
Ein Mandant mit hoher Last beeintraechtigt andere Mandanten auf derselben gemeinsamen Infrastruktur.
8Kann man Modelle spaeter kombinieren?
Ja, viele Anbieter starten mit Shared Schema und migrieren einzelne Mandanten spaeter in isoliertere Modelle.
9Reicht Row Level Security allein?
Als Zusatzschutz ja, ersetzt aber keine sorgfaeltige Architektur mit korrekt gesetztem Mandantenkontext.
10Welches Modell ist am guenstigsten?
Shared Schema mit tenant_id, weil alle Ressourcen fuer alle Mandanten gemeinsam verwaltet werden.