Supabase-Datenbankdesign: Tabellenstruktur, Beziehungen und Row Level Security – vollständiger Leitfaden

Ich starre auf die rote Warnung im Supabase Dashboard – „RLS not enabled“. Sofort schießen Fragen durch den Kopf: Könnten Nutzerdaten zu Artikeln durchsickern? Stimmt diese Fremdschlüsselbeziehung? Wie baut man eine n:m-Beziehung richtig auf?
Als ich Supabase das erste Mal nutzte, bin ich in viele Fallen gelaufen. Nach dem Erstellen von Tabellen habe ich RLS vergessen – plötzlich konnte jeder alle Daten lesen. Fremdschlüssel waren unsauber modelliert: Nutzer gelöscht, Artikel blieben. Bei n:m-Beziehungen habe ich sogar Arrays ausprobiert – ein totales Desaster.
Nach einigen Monaten habe ich das Muster für Supabase-Datenbankdesign verstanden. Dieser Artikel fasst die Erfahrungen zusammen.
1. Tabellenstruktur: Namenskonventionen in PostgreSQL
1.1 Namenskonvention: snake_case ist der richtige Weg
PostgreSQL hat eine Eigenheit: Ohne doppelte Anführungszeichen werden Bezeichner in Kleinbuchstaben umgewandelt. Mit Anführungszeichen bleibt die Schreibweise exakt erhalten.
Was bedeutet das? Bei CamelCase (UserProfile) müssen Sie überall Anführungszeichen setzen. Das ist mühsam.
Deshalb gilt in der PostgreSQL-Community: snake_case (Unterstrich-Trennung), Plural für Tabellennamen, Singular für Spaltennamen.
-- ✅ Empfohlen
CREATE TABLE users (
id UUID PRIMARY KEY,
email TEXT UNIQUE,
created_at TIMESTAMPTZ
);
1.2 Spaltentypen: Nicht in MySQL-Denkmuster verfangen
Fehler 1: VARCHAR statt TEXT
In PostgreSQL sind TEXT und VARCHAR performancegleich. Der Unterschied: VARCHAR(n) hat eine Längenbegrenzung. Wenn Sie keine brauchen, nutzen Sie direkt TEXT.
Fehler 2: TIMESTAMP statt TIMESTAMPTZ
TIMESTAMP speichert keine Zeitzoneninformation. Server in den USA, Nutzer in China – die Anzeige wird chaotisch. TIMESTAMPTZ konvertiert Zeitzonen automatisch.
Fehler 3: SERIAL statt UUID
SERIAL ist eine autoinkrementierende Ganzzahl. Für Single-Server-Anwendungen okay, in verteilten Systemen entstehen Kollisionen. UUID ist global eindeutig.
2. Drei Beziehungstypen: 1:1, 1:n und n:m
2.1 Eins-zu-eins: UNIQUE reicht
Typisches Szenario: Nutzer und Profil.
CREATE TABLE profiles (
id UUID PRIMARY KEY,
user_id UUID UNIQUE REFERENCES users(id) ON DELETE CASCADE,
bio TEXT
);
Der Schlüssel: user_id UUID UNIQUE. Die UNIQUE-Constraint stellt sicher, dass jeder Nutzer genau ein Profil hat.
2.2 Eins-zu-viele: Der klassische Fremdschlüssel
Autoren und Bücher. Ein Autor kann viele Bücher schreiben.
CREATE TABLE books (
id UUID PRIMARY KEY,
author_id UUID REFERENCES authors(id) ON DELETE CASCADE,
title TEXT
);
Bei Abfragen kann Supabase JS verknüpfte Daten direkt verschachtelt laden.
2.3 Viele-zu-viele: Die Verknüpfungstabelle ist entscheidend
Studierende und Kurse. Ein Studierender kann mehrere Kurse belegen, ein Kurs hat mehrere Studierende.
Lösung: eine Verknüpfungstabelle.
CREATE TABLE enrollments (
student_id UUID REFERENCES students(id) ON DELETE CASCADE,
course_id UUID REFERENCES courses(id) ON DELETE CASCADE,
PRIMARY KEY (student_id, course_id)
);
3. Row Level Security: Die Datenbank als Türsteher
3.1 Die „Standardverweigerung“-Philosophie von RLS
Beim ersten Supabase-Projekt habe ich eine posts-Tabelle angelegt und mit dem anon key vom Frontend abgefragt. Ergebnis: alle Daten kamen zurück. Schock.
Supabase aktiviert Row Level Security (RLS) standardmäßig nicht. Ohne RLS kann jeder mit dem anon key alle Daten lesen und schreiben.
Deshalb die erste Regel: Nach dem Erstellen einer Tabelle sofort RLS aktivieren.
ALTER TABLE posts ENABLE ROW LEVEL SECURITY;
Aktiviert – und fertig? Noch nicht. RLS ohne Policy bedeutet „Zugriff für alle verweigert“. Mindestens eine Policy ist Pflicht.
3.2 Policy-Syntax: USING und WITH CHECK
- USING: filtert bestehende Zeilen (SELECT, UPDATE, DELETE)
- WITH CHECK: prüft neue Zeilen (INSERT, UPDATE)
3.3 Vier häufige Policy-Muster
Muster 1: Nutzer greifen auf eigene Daten zu
CREATE POLICY "Users manage own data"
ON posts FOR ALL
TO authenticated
USING (user_id = auth.uid());
Muster 2: Öffentliche und private Daten gemischt
Veröffentlichte Inhalte für alle sichtbar, Entwürfe nur für den Autor.
Muster 3: Mandantenisolation
Teammitglieder sehen nur Daten ihres eigenen Teams.
Muster 4: RBAC-Rollensteuerung
Administratoren haben erweiterte Rechte.
4. RLS-Performance-Optimierung
4.1 Performance-Killer: Subquery pro Zeile
Subqueries in RLS-Policies werden für jede Zeile ausgeführt. Bei 100.000 Zeilen und einer Subquery zur Teamprüfung: Timeout nach 3 Minuten.
4.2 Optimierung 1: Indizes hinzufügen
Spalten, die in RLS-Policies vorkommen, brauchen Indizes.
CREATE INDEX idx_posts_user_id ON posts(user_id);
Offizieller Supabase-Test: ohne Index 450 ms, mit Index 45 ms – Faktor 10.
4.3 Optimierung 2: SECURITY DEFINER-Funktionen
Subqueries in eine Funktion auslagern – sie läuft nur einmal.
CREATE OR REPLACE FUNCTION user_teams()
RETURNS SETOF UUID
LANGUAGE SQL SECURITY DEFINER STABLE
AS $$ SELECT team_id FROM team_members WHERE user_id = auth.uid(); $$;
5. Praxisbeispiele
5.1 Blog-System: Artikel, Kategorien, Tags
Vollständige Umsetzung mit Tabellenstruktur, RLS-Policies und Index-Konfiguration.
5.2 Multi-Tenant-SaaS: Team-Zusammenarbeit
Team-Datenisolation, Zugriff für Teammitglieder, Admin-Rechte.
Zusammenfassung
Kernpunkte:
- snake_case-Namensgebung
- UUID als Primärschlüssel, TEXT für Strings, TIMESTAMPTZ für Zeitstempel
- RLS ist Pflicht
- Index + SECURITY DEFINER-Funktionen für Performance
FAQ
Muss RLS direkt nach der Tabellenerstellung aktiviert werden?
Warum empfiehlt PostgreSQL snake_case?
Warum sollte man in RLS-Policies kein FOR ALL verwenden?
Wie prüfe ich den RLS-Status?
4 Min. Lesezeit · Veröffentlicht am: 4. Apr. 2026 · Aktualisiert am: 14. Juli 2026
Supabase in der Praxis
Wenn du über die Suche hier gelandet bist, kommst du am schnellsten weiter, indem du zum vorherigen oder nächsten Beitrag dieser Serie springst.
Vorheriger
Supabase Einstieg: PostgreSQL + Auth + Storage als All-in-One-Backend
Supabase ist die Open-Source-Alternative zu Firebase mit PostgreSQL-Datenbank, Enterprise-Authentifizierung, Objektspeicher und Echtzeit-Sync. Dieses Tutorial führt Sie durch die drei Kernfunktionen – mit vollständigen Codebeispielen und Praxisprojekt, ideal für Frontend-Entwickler beim schnellen Aufbau von Full-Stack-Apps.
Teil 1 von 10
Nächster
Supabase Auth in der Praxis: E-Mail-Verifizierung, OAuth und Session-Management
Supabase Auth Praxisleitfaden: E-Mail-Verifizierung konfigurieren, OAuth integrieren, JWT-Session-Management und PKCE-Flow. Alles für die Benutzerauthentifizierung an einem Ort.
Teil 3 von 10
Ähnliche Beiträge
Supabase Storage in der Praxis: Upload, Berechtigungen und CDN-Beschleunigung

Supabase Storage in der Praxis: Upload, Berechtigungen und CDN-Beschleunigung
Supabase Realtime in der Praxis: Drei Modi im Vergleich und kollaborative Apps


Kommentare
Melde dich mit GitHub an, um einen Kommentar zu hinterlassen