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.
Aber: Mehrkundenfähigkeit ist anspruchsvoller in Architektur und Sicherheit. Nicht jede SaaS braucht sie, gerade kleine, spezialisierte Werkzeuge kommen oft ohne aus.
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 extrahierentenant_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.
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;
}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.
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.
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-backupCode-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;
}Kosten: In der Regel am teuersten, weil Datenbanken, Backups und Monitoring pro Tenant stärker getrennt betrieben werden.
| Aspekt | Shared DB, Shared Schema | Shared DB, Schema-per-Tenant | DB-per-Tenant |
|---|---|---|---|
| Sicherheit | Niedrig (RLS komplex) | Mittel | Sehr hoch |
| Kosten | am günstigsten | mittel | am höchsten |
| Performance-Isolation | Gering | Mittel | Sehr hoch |
| Upgrade-Komplexität | Gering | Mittel | Hoch |
| Datenlöschung | Komplex | Mittel | Trivial |
| Compliance-freundlich | abhängig von Umsetzung | oft gut | oft sehr gut |
| Ideal für | SaaS in der Frühphase | Mittlere SaaS mit moderater Compliance | Enterprise, Gesundheit, Finanz |
Die meisten Vibecoding-Prototypen starten Single-Tenant, also mit einem einzigen Tenant — meist du selbst. Das ist sinnvoll, weil du schnell validieren willst.
Du hast einen Prototyp mit Lovable gebaut. Users-Tabelle, keine Multi-Tenancy. Jetzt kommen Kunden.
-- 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');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);// 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);
}tenant_id im Request zu ändern → RLS blockiert.Viele Startups setzen Claude, GPT-4 oder Embeddings in ihrer SaaS ein. Mit mehreren Tenants und LLMs wird Kostenkontrolle entscheidend:
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.
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.
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.
Mit korrekt konfigurierten RLS-Policies ja. Es ist aber die fehleranfälligste Variante. Ein Fehler in den Policies bedeutet ein Datenleck.
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.
Nein. DSGVO geht es um Datenlöschung und Datenschutz — jedes Modell kann DSGVO-konform sein. DB-per-Tenant hilft aber beim Audit-Trail.
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.
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.