Direkte Antwort

Multi-Tenancy in drei Sätzen

Multi-Tenancy (auf Deutsch: Mehrkundenfähigkeit) ist die Architektur, bei der eine einzelne Software-Instanz mehrere unabhängige Kunden („Tenants“) bedient, ohne dass diese sich gegenseitig sehen oder beeinflussen. Jeder Tenant hat den Eindruck, eine eigene, dedizierte Anwendung zu nutzen — technisch teilen sich alle aber Infrastruktur und Code.

Das Gegenteil ist Single-Tenancy: jeder Kunde erhält seine eigene App-Instanz und oft auch eine eigene Datenbank. Mehrkundenfähigkeit ist wirtschaftlicher, aber in Architektur und Sicherheit anspruchsvoller.

Warum überhaupt

Warum Mehrkundenfähigkeit?

  • Wirtschaftlich: Eine Codebasis, viele Kunden, tiefere Kosten pro Tenant.
  • Operativ: Einfachere Updates, alle Kunden bekommen neue Features zur gleichen Zeit.
  • Skalierbar: Neue Kunden landen einfach als neue Tenant-Daten in der bestehenden Infrastruktur.

Aber: Mehrkundenfähigkeit ist anspruchsvoller in Architektur und Sicherheit. Nicht jede SaaS braucht sie, gerade kleine, spezialisierte Werkzeuge kommen oft ohne aus.

Modell 1

Shared Database, Shared Schema (100% Pooling)

Aufbau: Alle Tenants teilen sich exakt eine Datenbank und ein Schema. Jede Tabelle hat eine tenant_id-Spalte.

CREATE TABLE users (
  id SERIAL PRIMARY KEY,
  tenant_id UUID NOT NULL,  -- Welcher Tenant gehört dieser Nutzer?
  email VARCHAR NOT NULL,
  name VARCHAR NOT NULL,
  created_at TIMESTAMP DEFAULT NOW(),
  UNIQUE(tenant_id, email)   -- Email ist pro Tenant unique
);

CREATE INDEX idx_users_tenant ON users(tenant_id);

Sicherheit: Bei Shared Schema braucht es eine konsequente Isolation auf Datenbank- oder Zugriffsschicht, zum Beispiel Postgres RLS oder Supabase Row-Level Policies.

CREATE POLICY "Users can only see their own tenant's data"
ON users FOR SELECT
USING (tenant_id = auth.uid()); -- Vereinfacht; in Realität: JWT-Tenant-ID extrahieren

Stärken

  • Günstigste Infrastruktur.
  • Einfachste Migrations-Historie.
  • Schnelle Feature-Rollouts mit einem einzigen Code-Deploy.

Schwächen

  • Höchstes Sicherheitsrisiko: Bei falsch konfigurierten RLS-Policies sieht Tenant A die Daten von Tenant B.
  • Schwer zu analysieren („Warum sieht Nutzer X diese Daten?“).
  • Alle Tenants teilen sich die DB-Performance. Ein Tenant mit schlechten Abfragen kann andere ausbremsen.
  • Datenlöschung aufwendig: Du musst alle Referenzen mit tenant_id kennen.

Kosten: Meist deutlich tiefer als Single-Tenancy, weil viele Tenants Infrastruktur teilen. Die konkrete Ersparnis hängt aber von Last, Datenvolumen und Betrieb ab.

Modell 2

Shared Database, Schema-per-Tenant

Aufbau: Ein Datenbank-Server, aber jeder Tenant sein eigenes Schema (in Postgres: tenant_123.users, tenant_456.users).

CREATE SCHEMA tenant_123;
CREATE SCHEMA tenant_456;

CREATE TABLE tenant_123.users (id SERIAL, name VARCHAR, ...);
CREATE TABLE tenant_456.users (id SERIAL, name VARCHAR, ...);

Code-Seite (z.B. Node.js):

const pool = new Pool({
  connectionString: `postgres://user:pass@localhost/main_db`
});

async function getUsersForTenant(tenantId) {
  const result = await pool.query(
    `SELECT * FROM tenant_${tenantId}.users`
  );
  return result.rows;
}

Sicherheit

Einfacher als Shared Schema: Postgres erlaubt es, bestimmten DB-Nutzern nur auf bestimmte Schemas Zugriff zu geben. Aber: Im Code musst du dennoch garantieren, dass nur auf das jeweils richtige Schema zugegriffen wird.

Stärken

  • Gute Balance zwischen Sicherheit und Kosten.
  • Tenants können bei Bedarf abweichende Schemas haben, das erlaubt spätere Anpassungen.
  • DB-Performance: Jeder Tenant hat sein eigenes Index-Set, keine gegenseitige Verlangsamung.

Schwächen

  • Risiko bei String-Interpolation: Wenn die Tenant-ID unsauber durchgereicht wird, droht SQL-Injection. Pflicht: parameterisierte Abfragen.
  • Schema-Migrationen über 1’000 Schemas brauchen Automatisierung.
  • Datenlöschung: jedes Schema muss einzeln bereinigt werden.

Kosten: Oft günstiger als DB-per-Tenant, aber aufwendiger als Shared Schema. Die konkrete Ersparnis hängt von Tenant-Anzahl, Datenvolumen und Automatisierung ab.

Modell 3

Database-per-Tenant (vollständige Isolation)

Aufbau: Jeder Tenant bekommt seine eigene Datenbank (und idealerweise: eigene Server, eigene Backups).

Tenant A  → PostgreSQL Instance tenant-a.internal → Backup tenant-a-backup
Tenant B  → PostgreSQL Instance tenant-b.internal → Backup tenant-b-backup
Tenant C  → PostgreSQL Instance tenant-c.internal → Backup tenant-c-backup

Code-Seite:

async function getTenantDbConnection(tenantId) {
  const dbConfig = await getTenantConfig(tenantId);
  return new Pool({
    connectionString: dbConfig.connectionString // z.B. postgres://user:pass@tenant-a.internal/db
  });
}

async function getUsersForTenant(tenantId) {
  const pool = await getTenantDbConnection(tenantId);
  const result = await pool.query(`SELECT * FROM users`);
  return result.rows;
}

Stärken

  • Höchste Isolation: Tenant A und Tenant B sind auf Datenbank-Ebene stark getrennt.
  • Sicherheit und Compliance: Ideal für Gesundheitswesen, Finanz und Pharma.
  • Performance-Isolation: Ein Tenant kann andere nicht ausbremsen.
  • Datenlöschung einfach: Lösche die ganze Datenbank.
  • Anpassbarkeit: Jeder Tenant bekommt sein eigenes Schema und seinen eigenen Backup-Plan.

Schwächen

  • Teuer: Viele DB-Instanzen bedeuten hohe Infrastrukturkosten.
  • Operativ aufwendig: Backup, Updates und Monitoring multiplizieren sich mit der Tenant-Anzahl.
  • Migrationen: Schema-Migrationen über 1’000 DBs brauchen viel Automatisierung.
  • Ressourcen-Ineffizienz: Ein kleiner Tenant zahlt für eine ganze DB-Instanz, auch wenn er nur 1 GB nutzt.

Kosten: In der Regel am teuersten, weil Datenbanken, Backups und Monitoring pro Tenant stärker getrennt betrieben werden.

Vergleich

Die drei Modelle im Direktvergleich

AspektShared DB, Shared SchemaShared DB, Schema-per-TenantDB-per-Tenant
SicherheitNiedrig (RLS komplex)MittelSehr hoch
Kostenam günstigstenmittelam höchsten
Performance-IsolationGeringMittelSehr hoch
Upgrade-KomplexitätGeringMittelHoch
DatenlöschungKomplexMittelTrivial
Compliance-freundlichabhängig von Umsetzungoft gutoft sehr gut
Ideal fürSaaS in der FrühphaseMittlere SaaS mit moderater ComplianceEnterprise, Gesundheit, Finanz
Migrationspfad

Typischer Weg: Single-Tenant zu Multi-Tenant

Die meisten Vibecoding-Prototypen starten Single-Tenant, also mit einem einzigen Tenant — meist du selbst. Das ist sinnvoll, weil du schnell validieren willst.

01

Vibecoding

Woche 1 bis 2
  • Code: eine users-Tabelle, keine tenant_id.
  • Ziel: Funktioniert die Logik?
02

Erste Traktion

Woche 3 bis 8
  • Erste Kunden zeigen Interesse.
  • Entscheidung: Single-Tenant (jeder Kunde bekommt eine eigene App-Instanz) oder Mehrkundenfähigkeit?
  • Für Single-Tenant: Deployment automatisieren (Terraform, Helm).
  • Für Mehrkundenfähigkeit: Architektur umbauen.
03

Härtung der Mehrkundenfähigkeit

Woche 9 bis 16
  • Modell wählen: Shared (am günstigsten), Schema-per-Tenant (ausgewogen), DB-per-Tenant (am sichersten).
  • Datenbank migrieren: tenant_id in allen Tabellen ergänzen, Migrationen schreiben.
  • Tenant-Kontext einbauen: Jede Anfrage muss die Tenant-ID kennen (Header, JWT-Claims, Subdomain).
  • RLS oder Schema-Routing aktivieren: Die Datenbank-Schicht schützt automatisch.
  • Isolation testen: Sicherheitstest, ob Nutzer A die Daten von Nutzer B nicht sehen kann.
In der Praxis

Nachträgliche Multi-Tenancy mit Postgres-RLS

Du hast einen Prototyp mit Lovable gebaut. Users-Tabelle, keine Multi-Tenancy. Jetzt kommen Kunden.

Schritt 1: Migriere die Tabelle

-- Alte Tabelle
ALTER TABLE users ADD COLUMN tenant_id UUID NOT NULL DEFAULT gen_random_uuid();

-- Künftig: Jeder User-Insert kennt tenant_id
-- INSERT INTO users (tenant_id, email, name) VALUES ('tenant-123', 'alice@co.com', 'Alice');

Schritt 2: Aktiviere Row-Level Security (Postgres RLS)

ALTER TABLE users ENABLE ROW LEVEL SECURITY;

CREATE POLICY "Users see only their tenant's data"
ON users FOR SELECT
USING (tenant_id = current_setting('app.tenant_id')::uuid);

CREATE POLICY "Users insert only for their tenant"
ON users FOR INSERT
WITH CHECK (tenant_id = current_setting('app.tenant_id')::uuid);

Schritt 3: Code passt Tenant-Context

// In Next.js API-Route
export async function GET(req) {
  const tenantId = req.headers['x-tenant-id']; // Oder aus JWT

  // Supabase Client mit Tenant-Context
  const { data, error } = await supabase
    .from('users')
    .select('*')
    .eq('tenant_id', tenantId);

  return Response.json(data);
}

Schritt 4: Test

  • Login als User von Tenant A, prüfe: Nur Tenant A’s Daten sichtbar.
  • Versuche, manuell tenant_id im Request zu ändern → RLS blockiert.
Erweiterung

Mehrkundenfähigkeit und KI-Kosten

Viele Startups setzen Claude, GPT-4 oder Embeddings in ihrer SaaS ein. Mit mehreren Tenants und LLMs wird Kostenkontrolle entscheidend:

  1. Limits pro Tenant: „Tenant A darf maximal 10’000 API-Aufrufe pro Monat machen.“
  2. Caching: Häufige Prompts zwischenspeichern (zum Beispiel mit Redis).
  3. Modell-Routing: Günstigere Modelle (Claude Haiku, GPT-3.5) für einfache Aufgaben, teure Modelle nur dort, wo sie nötig sind.
  4. Monitoring: Wer verursacht welche Kosten? Ein Dashboard pro Tenant macht das sichtbar.
FAQ

Häufige Fragen zu Multi-Tenancy

Muss ich Mehrkundenfähigkeit haben?

Nein. Single-Tenant (jeder Kunde bekommt seine eigene App) ist einfacher und teurer pro Kunde, aber in der frühen Phase oft die bessere Wahl.

Wann lohnt sich Mehrkundenfähigkeit?

Sie wird wirtschaftlich interessant, wenn mehrere Kunden denselben Betrieb, dieselben Updates und ähnliche Datenmodelle teilen. Eine feste Kundenzahl gibt es nicht; vorher können mehrere Single-Tenant-Instanzen sinnvoller sein.

Kann ich von Single-Tenant zu Multi-Tenant migrieren?

Ja. Der Aufwand hängt stark von Datenmodell, Code-Struktur und Risiko ab. Für kleine Systeme können wenige Wochen reichen, bei komplexen Datenmodellen braucht es mehr Planung, Migration und Sicherheitsprüfung.

Ist Shared Schema (Modell 1) sicher genug?

Mit korrekt konfigurierten RLS-Policies ja. Es ist aber die fehleranfälligste Variante. Ein Fehler in den Policies bedeutet ein Datenleck.

Welches Modell setzt Olai meistens ein?

Das entscheiden wir pro Projekt. Häufig prüfen wir Shared Schema mit klaren Policies, Schema-per-Tenant oder DB-per-Tenant. Entscheidend sind Isolation, Betriebskosten, Compliance-Anforderungen und Migrationsaufwand.

Brauche ich DB-per-Tenant für DSGVO-Konformität?

Nein. DSGVO geht es um Datenlöschung und Datenschutz — jedes Modell kann DSGVO-konform sein. DB-per-Tenant hilft aber beim Audit-Trail.

Wie sicher ist Row-Level Security in Postgres?

Postgres-RLS ist eine eingebaute Datenbank-Funktion und so sicher, wie du sie konfigurierst. Jede Query muss durch RLS gehen, sonst lecken Daten. Audit-Tests pro Mandant sind Pflicht. Auf unserer Infrastruktur erzwingen wir RLS-Policies zusätzlich über einen zentralen Repository-Layer.

Du brauchst Mehrkundenfähigkeit für deinen Prototyp?

Wir analysieren deinen Code, empfehlen das passende Modell und bauen die Migration inklusive Zugriffskontrollen und Isolations-Tests. Am besten passiert das vor der ersten echten Kunden-Anmeldung.