Supabase Einstieg: PostgreSQL + Auth + Storage als All-in-One-Backend

Ich starre auf den zwölften Datenbankverbindungsfehler auf dem Bildschirm und merke: Als Frontend-Entwickler ein Full-Stack-Projekt zu bauen, ist wirklich schwer.
Früher musste man für jedes Backend-Feature Node.js, Express, Datenbankkonfiguration, Benutzerauthentifizierung und Dateispeicher lernen – jedes davon eine eigene Hürde. Bis Supabase auftauchte.
Kurz gesagt: Supabase ist die Open-Source-Alternative zu Firebase – aber mit PostgreSQL statt dem oft frustrierenden NoSQL. Datenbank, Authentifizierung und Dateispeicher sind in einem Paket gebündelt: Backend as a Service aus einer Hand.
Dieser Artikel führt Sie von Grund auf durch Supabase und konzentriert sich auf die drei Kernfunktionen: Database, Auth und Storage. Danach können Sie damit ein vollständiges Backend schnell aufsetzen – ohne sich in Konfigurationsdateien zu verlieren.
Was ist Supabase?
Zuerst die Grundfrage: Was ist Supabase eigentlich?
Es ist eine BaaS-Plattform – Backend as a Service. Das heißt: Sie müssen keinen eigenen Server betreiben, keine Datenbank konfigurieren und keine API schreiben – Supabase übernimmt das.
Anders als Firebase ist Supabase vollständig Open Source. Und es nutzt PostgreSQL – das ist wichtig. PostgreSQL ist eine relationale Datenbank: komplexe SQL-Abfragen, klare Datenbeziehungen – deutlich angenehmer als dokumentenorientierte Datenbanken wie Firestore.
Supabase bietet sechs Kernfunktionen:
- Database: PostgreSQL-Datenbank mit SQL-Abfragen und automatisch generierter REST-API
- Auth: Benutzerauthentifizierung mit E-Mail-Login, Social Login (Google, GitHub usw.) und JWT Token
- Storage: Dateispeicher ähnlich AWS S3, aber einfacher
- Realtime: Echtzeit-Datensynchronisation – ideal für Chat-Apps
- Edge Functions: Edge-Computing ähnlich AWS Lambda
- Vector Database: Vektordatenbank – ideal für KI-Anwendungen
In diesem Artikel geht es nur um die ersten drei: Database, Auth und Storage – das Herzstück. Die übrigen Funktionen behandeln wir später.
Vielleicht fragen Sie sich: Open Source, PostgreSQL, Auth und Storage – wie schlägt sich Supabase gegen Firebase? Das kommt ausführlich weiter unten. Kurz: Bei SQL-Abfragen, komplexen Beziehungen oder voller Datenkontrolle → Supabase. Bei Mobile-First und besonders starker Echtzeit-Sync → Firebase.
Schnellstart
Supabase-Projekt erstellen
Schritt eins: Registrieren Sie sich auf supabase.com. Danach klicken Sie auf „New Project“, um ein neues Projekt anzulegen.
Beim Anlegen benötigen Sie:
- Projektname: beliebig, z. B.
my-first-app - Datenbankpasswort: unbedingt notieren – wird später gebraucht
- Region: nächstgelegene wählen; für Asien Singapore oder Tokyo
In etwa drei Minuten ist das Projekt bereit. Im Dashboard sehen Sie links viele Menüpunkte: Table Editor, Authentication, Storage, Edge Functions … Keine Sorge – dieser Artikel führt Sie Schritt für Schritt durch.
Installation und Initialisierung
Als Nächstes Supabase im Frontend-Projekt einbinden. Abhängigkeit installieren:
npm install @supabase/supabase-js
Im Supabase Dashboard benötigen Sie zwei Werte: Project URL und Anon Public Key – unter Settings > API.
Supabase Client initialisieren:
import { createClient } from '@supabase/supabase-js';
const supabaseUrl = 'https://your-project-id.supabase.co';
const supabaseAnonKey = 'your-anon-public-key';
export const supabase = createClient(supabaseUrl, supabaseAnonKey);
Dieser Code ist Ihr Einstiegspunkt zu Supabase. Alle weiteren Operationen – Datenbankabfragen, Login, Datei-Upload – laufen über das supabase-Objekt.
Verbindungstest
Nach der Initialisierung kurz prüfen, ob die Verbindung steht. Am einfachsten: eine Abfrage auf die Datenbank:
const { data, error } = await supabase.from('users').select('*');
if (error) {
console.error('Verbindung fehlgeschlagen:', error.message);
} else {
console.log('Verbindung erfolgreich!', data);
}
Fehlt die Tabelle users, ist das normal – die legen Sie im nächsten Abschnitt an.
Typische Fehler:
- URL oder Key falsch kopiert – vollständige Werte prüfen
- CORS-Fehler – selten nötig, Supabase erlaubt Frontend-Zugriff standardmäßig
- Netzwerkprobleme – gelegentlich; ein paar Minuten warten und erneut versuchen
Bei Erfolg erhalten Sie Daten zurück – oft ein leeres Array [], wenn die Tabelle noch leer ist.
Database: Datenbankoperationen
Das ist das Herz von Supabase. Wer PostgreSQL kennt, fühlt sich heimisch; als Frontend-Entwickler ohne SQL-Erfahrung hilft der visuelle Table Editor – Datenbankoperationen ohne SQL sind möglich.
Datentabelle anlegen
Zwei Wege: Table Editor (visuell) oder SQL.
Table Editor: Links „Table Editor“ wählen, dann „Create a new table“. Tabellenname, Feldnamen und Feldtypen eingeben.
Beispiel – Tabelle users:
| Feldname | Typ | Einschränkung |
|---|---|---|
| id | int8 | Primary Key, Auto Increment |
| text | Unique, Not Null | |
| name | text | - |
| created_at | timestamptz | Default: now() |
Mit „Save“ ist die Tabelle erstellt.
Persönlich finde ich SQL schneller – besonders für komplexere Operationen später. Den SQL Editor finden Sie links im Dashboard.
SQL für users- und projects-Tabellen:
-- Nutzertabelle
CREATE TABLE users (
id SERIAL PRIMARY KEY,
email TEXT UNIQUE NOT NULL,
name TEXT,
created_at TIMESTAMPTZ DEFAULT NOW()
);
-- Projekt-Tabelle
CREATE TABLE projects (
id SERIAL PRIMARY KEY,
user_id INTEGER REFERENCES users(id),
title TEXT NOT NULL,
description TEXT,
status TEXT DEFAULT 'active',
created_at TIMESTAMPTZ DEFAULT NOW()
);
Wichtiges Detail: user_id in projects ist ein Foreign Key zu users.id. Jedes Projekt gehört einem Nutzer – der Vorteil relationaler Datenbanken: klare Beziehungen.
CRUD-Operationen
Tabellen stehen – jetzt Create, Read, Update, Delete testen.
Daten einfügen:
// Nutzer einfügen
const { data, error } = await supabase
.from('users')
.insert([
{ email: '[email protected]', name: 'John Doe' }
]);
if (error) {
console.error('Einfügen fehlgeschlagen:', error.message);
} else {
console.log('Einfügen erfolgreich:', data);
}
Daten abfragen:
// Alle Projekte mit zugehörigen Nutzerdaten
const { data, error } = await supabase
.from('projects')
.select(`
*,
users (
name,
email
)
`)
.eq('status', 'active')
.order('created_at', { ascending: false });
console.log(data);
Diese Abfrage holt nicht nur projects, sondern über den Foreign Key auch die verknüpften Nutzerdaten – eine Abfrage, zwei Tabellen. In Firestore wären mehrere Runden und manuelles Zusammenführen nötig.
Daten aktualisieren:
const { data, error } = await supabase
.from('projects')
.update({ status: 'completed' })
.eq('id', 1);
Daten löschen:
const { data, error } = await supabase
.from('projects')
.delete()
.eq('id', 1);
Die Operationen sind intuitiv. .eq() bedeutet „gleich“. Weitere Filter: .gt() (größer), .lt() (kleiner), .like() (Muster) – die gängigen SQL-Filter sind abgedeckt.
Row Level Security (RLS)
Besonders wichtig bei nutzerbezogenen Funktionen.
RLS steht für Row Level Security – Zeilenebenen-Sicherheit. Sie steuern, dass Nutzer nur eigene Daten sehen, nicht fremde.
Beispiel: In projects liegen viele Einträge – nach dem Login soll jeder nur eigene Projekte sehen.
RLS aktivieren:
ALTER TABLE projects ENABLE ROW LEVEL SECURITY;
Policy anlegen:
-- Nutzer sehen nur eigene Projekte
CREATE POLICY "Users can view their own projects"
ON projects FOR SELECT
USING (user_id = auth.uid());
auth.uid() ist eine Supabase-Funktion und liefert die ID des angemeldeten Nutzers. Diese Policy bedeutet: Beim SELECT auf projects nur Zeilen mit user_id = aktuelle Nutzer-ID.
Analog Policies für INSERT, UPDATE und DELETE:
-- Nutzer dürfen nur eigene Projekte einfügen
CREATE POLICY "Users can insert their own projects"
ON projects FOR INSERT
WITH CHECK (user_id = auth.uid());
-- Nutzer dürfen nur eigene Projekte aktualisieren
CREATE POLICY "Users can update their own projects"
ON projects FOR UPDATE
USING (user_id = auth.uid())
WITH CHECK (user_id = auth.uid());
-- Nutzer dürfen nur eigene Projekte löschen
CREATE POLICY "Users can delete their own projects"
ON projects FOR DELETE
USING (user_id = auth.uid());
Selbst bei böswilligen Abfragen fremder Daten blockiert die Datenbank – deutlich sicherer als Prüfungen im Frontend.
Auth: Benutzerauthentifizierung
Supabase Auth ist umfangreich: E-Mail/Passwort, passwortloser Login (Magic Link), OTP, Social Login (Google, GitHub, Apple und 20+ Plattformen), Telefon-Login und Enterprise-SSO.
Überblick über die Authentifizierung
Kernmechanismus: JWT Token – JSON Web Token. Nach erfolgreichem Login erzeugt Supabase ein Token; das Frontend sendet es bei API-Anfragen mit, das Backend prüft die Identität.
Supabase Auth speichert Nutzerdaten automatisch in der PostgreSQL-Tabelle auth.users – diese Tabelle existiert von Anfang an. Nutzer-ID, E-Mail, Erstellungszeit, letzter Login – alles dort.
Session Persistence: Nach dem Login merkt sich der Browser den Zustand; beim nächsten Besuch kein erneuter Login nötig. Das Supabase-Frontend-SDK übernimmt das automatisch.
Email/Password-Authentifizierung
Die häufigste Methode. Zuerst Registrierung:
// Nutzer registrieren
const { data, error } = await supabase.auth.signUp({
email: '[email protected]',
password: 'securepassword123',
});
if (error) {
console.error('Registrierung fehlgeschlagen:', error.message);
} else {
console.log('Registrierung erfolgreich:', data);
}
Nach der Registrierung sendet Supabase eine Bestätigungs-E-Mail. Klick auf den Link aktiviert das Konto – Standardverhalten, im Dashboard deaktivierbar, aber nicht empfohlen: E-Mail-Bestätigung verhindert Missbrauch.
Anmeldung:
// Nutzer anmelden
const { data, error } = await supabase.auth.signInWithPassword({
email: '[email protected]',
password: 'securepassword123',
});
if (error) {
console.error('Anmeldung fehlgeschlagen:', error.message);
} else {
console.log('Anmeldung erfolgreich:', data);
}
Nach erfolgreichem Login Nutzerdaten abrufen:
// Aktuell angemeldeten Nutzer abrufen
const { data: { user } } = await supabase.auth.getUser();
console.log('Aktueller Nutzer:', user);
// Ausgabe ähnlich: { id: 'abc123', email: '[email protected]', ... }
Abmeldung:
await supabase.auth.signOut();
Danach ist die Session geleert – erneute Anmeldung nötig.
Passwort zurücksetzen – eingebaute Funktion:
// E-Mail zum Passwort-Reset senden
const { data, error } = await supabase.auth.resetPasswordForEmail(
'[email protected]'
);
Der Nutzer erhält eine E-Mail und setzt das Passwort über den Link – ohne zusätzliche Logik Ihrerseits.
Social Auth
Beliebt, weil Nutzer ohne Formular mit Google oder GitHub anmelden können.
Konfiguration im Dashboard: Authentication > Providers – gewünschte Plattform aktivieren, z. B. Google oder GitHub.
Pro Plattform ähnliche Schritte:
- OAuth App bei Google/GitHub anlegen
- Client ID und Client Secret in Supabase eintragen
- Redirect URL konfigurieren
Frontend-Code:
// Google-Login
const { data, error } = await supabase.auth.signInWithOAuth({
provider: 'google',
});
// GitHub-Login
const { data, error } = await supabase.auth.signInWithOAuth({
provider: 'github',
});
Die Seite leitet zu Google/GitHub weiter; nach Zustimmung zurück in Ihre App – Login abgeschlossen.
Callback-URL und Zusatzparameter anpassen:
const { data, error } = await supabase.auth.signInWithOAuth({
provider: 'google',
options: {
redirectTo: 'https://your-app.com/dashboard',
queryParams: {
access_type: 'offline',
prompt: 'consent',
}
}
});
redirectTo: Zielseite nach erfolgreichem Login. queryParams: zusätzliche OAuth-Parameter, z. B. Offline-Zugriff oder erneute Zustimmung.
RLS mit Auth verbinden
Bei RLS wurde auth.uid() erwähnt – jetzt wird der Zusammenhang klar.
Nach dem Login liefert auth.uid() die Nutzer-ID. In Database-Policies nutzen Sie diese ID für „Nutzer sehen nur eigene Daten“.
Beispiel: Projekt anlegen und automatisch dem aktuellen Nutzer zuordnen.
// Projekt erstellen, automatisch aktuellem Nutzer zuordnen
const { data: { user } } = await supabase.auth.getUser();
const { data, error } = await supabase
.from('projects')
.insert([
{
title: 'New Project',
user_id: user.id // Nutzer-ID aus Auth
}
]);
RLS-Policies stellen sicher:
- SELECT: nur Projekte mit
user_id = auth.uid() - INSERT:
user_idmussauth.uid()entsprechen - UPDATE und DELETE analog
Authentifizierung und Berechtigungen sind damit durchgängig verbunden – Login, Datenzuordnung, Zugriffsbeschränkung in einer Linie.
Storage: Dateispeicher
Supabase Storage ist Objektspeicher ähnlich AWS S3 – deutlich einfacher in der Handhabung. Ideal für Avatare, Bilder und Dokumente.
Überblick Storage
Zwei Kernkonzepte: Bucket und Object.
- Bucket: Speicherbehälter, vergleichbar mit Ordnern. Mehrere Buckets möglich – z. B.
avatarsfür Profilbilder,documentsfür Dokumente - Object: konkrete Datei, z. B.
avatar.jpg,report.pdf
Zwei Berechtigungsmodi:
- Public: öffentlicher Bucket – jeder kann Dateien abrufen (öffentliche Bilder)
- Private: privater Bucket – Zugriff nur mit Berechtigung (vertrauliche Dokumente)
Bucket anlegen
Im Dashboard Storage wählen, dann „New Bucket“.
Beispiel avatars für Profilbilder:
- Name:
avatars - Public bucket: aktivieren (Avatare sind meist öffentlich)
- File size limit: z. B. 2 MB
Danach können Dateien hochgeladen werden.
Datei-Upload und -Download
Upload:
// Avatar hochladen
const file = document.getElementById('avatar-input').files[0];
const { data, error } = await supabase.storage
.from('avatars')
.upload('user-id/avatar.jpg', file, {
cacheControl: '3600',
upsert: false
});
if (error) {
console.error('Upload fehlgeschlagen:', error.message);
} else {
console.log('Upload erfolgreich:', data);
}
Details:
- Erster Parameter von
upload(): Dateipfad'user-id/avatar.jpg' cacheControl: Cache-Dauer in Sekunden, hier 3600upsert: bei existierender Datei überschreiben?false= Fehler;true= überschreiben
Download:
// Datei herunterladen
const { data, error } = await supabase.storage
.from('avatars')
.download('user-id/avatar.jpg');
if (error) {
console.error('Download fehlgeschlagen:', error.message);
} else {
// data ist ein Blob – in URL für Anzeige umwandeln
const url = URL.createObjectURL(data);
document.getElementById('avatar-img').src = url;
}
Bei öffentlichen Buckets direkt die öffentliche URL:
// Öffentliche URL abrufen
const { data } = supabase.storage
.from('avatars')
.getPublicUrl('user-id/avatar.jpg');
console.log('Öffentliche URL:', data.publicUrl);
// z. B.: https://your-project.supabase.co/storage/v1/object/public/avatars/user-id/avatar.jpg
Private Buckets: temporäre URL erzeugen:
// Temporäre URL (1 Stunde gültig)
const { data, error } = await supabase.storage
.from('documents')
.createSignedUrl('private-file.pdf', 3600);
console.log('Temporäre URL:', data.signedUrl);
Datei löschen:
const { data, error } = await supabase.storage
.from('avatars')
.remove(['user-id/avatar.jpg']);
Zugriffskontrolle
Storage unterstützt RLS-Policies – steuern, welche Dateien ein Nutzer nutzen darf.
Beispiel: Nutzer dürfen nur in den eigenen Ordner hochladen und Dateien dort abrufen.
-- Nutzer dürfen nur in eigenen Ordner hochladen
CREATE POLICY 'Users can upload to their own folder'
ON storage.objects FOR INSERT
WITH CHECK (
bucket_id = 'avatars' AND
(storage.foldername(name))[1] = auth.uid()::text
);
-- Nutzer dürfen nur eigene Dateien abrufen
CREATE POLICY 'Users can access their own files'
ON storage.objects FOR SELECT
USING (
bucket_id = 'avatars' AND
(storage.foldername(name))[1] = auth.uid()::text
);
storage.foldername(name) extrahiert den Ordner aus dem Pfad. [1] ist der erste Ordnername – die Nutzer-ID.
Upload-Pfad muss user-id/filename sein – RLS prüft, ob user-id der aktuellen Nutzer-ID entspricht. Sonst wird abgelehnt.
Praxisprojekt: Task-Management-App
Alles zusammen in einem Beispiel.
Einfache Task-Management-App mit:
- Registrierung und Login
- Aufgaben anlegen und Liste anzeigen
- Anhänge hochladen
Datenbankdesign
Tabellenstruktur:
-- Nutzertabelle (von Auth automatisch, nicht manuell anlegen)
-- tasks-Tabelle
CREATE TABLE tasks (
id SERIAL PRIMARY KEY,
user_id UUID REFERENCES auth.users(id) NOT NULL,
title TEXT NOT NULL,
description TEXT,
status TEXT DEFAULT 'pending' CHECK (status IN ('pending', 'completed')),
created_at TIMESTAMPTZ DEFAULT NOW(),
updated_at TIMESTAMPTZ DEFAULT NOW()
);
-- RLS aktivieren
ALTER TABLE tasks ENABLE ROW LEVEL SECURITY;
-- Policy: Nutzer verwalten nur eigene Tasks
CREATE POLICY 'Users can manage their own tasks'
ON tasks FOR ALL
USING (user_id = auth.uid())
WITH CHECK (user_id = auth.uid());
-- attachments-Tabelle (Tasks zugeordnet)
CREATE TABLE task_attachments (
id SERIAL PRIMARY KEY,
task_id INTEGER REFERENCES tasks(id) ON DELETE CASCADE,
file_name TEXT NOT NULL,
file_path TEXT NOT NULL,
file_size INTEGER,
created_at TIMESTAMPTZ DEFAULT NOW()
);
-- RLS aktivieren
ALTER TABLE task_attachments ENABLE ROW LEVEL SECURITY;
-- Policy: Berechtigung über Task-Zuordnung
CREATE POLICY 'Users can manage attachments of their tasks'
ON task_attachments FOR ALL
USING (
EXISTS (
SELECT 1 FROM tasks
WHERE tasks.id = task_attachments.task_id
AND tasks.user_id = auth.uid()
)
);
Bei task_attachments prüft die Policy nicht direkt user_id, sondern über task_id die tasks-Tabelle und deren user_id. Nur der Task-Eigentümer verwaltet Anhänge.
Storage Bucket anlegen
Bucket task-files als privat:
-- Im Dashboard oder per SQL
INSERT INTO storage.buckets (name, public)
VALUES ('task-files', false);
-- Policy: Upload nur in eigenen Ordner
CREATE POLICY 'Users can upload task files'
ON storage.objects FOR INSERT
WITH CHECK (
bucket_id = 'task-files' AND
(storage.foldername(name))[1] = auth.uid()::text
);
CREATE POLICY 'Users can access task files'
ON storage.objects FOR SELECT
USING (
bucket_id = 'task-files' AND
(storage.foldername(name))[1] = auth.uid()::text
);
Kernimplementierung
Alles zusammengeführt:
import { createClient } from '@supabase/supabase-js';
const supabase = createClient(
'https://your-project.supabase.co',
'your-anon-key'
);
// 1. Registrierung
async function register(email: string, password: string) {
const { data, error } = await supabase.auth.signUp({
email,
password,
});
if (error) throw error;
return data;
}
// 2. Anmeldung
async function login(email: string, password: string) {
const { data, error } = await supabase.auth.signInWithPassword({
email,
password,
});
if (error) throw error;
return data;
}
// 3. Task erstellen
async function createTask(title: string, description?: string) {
const { data: { user } } = await supabase.auth.getUser();
if (!user) throw new Error('Nicht angemeldet');
const { data, error } = await supabase
.from('tasks')
.insert([
{
title,
description,
user_id: user.id,
}
])
.select();
if (error) throw error;
return data[0];
}
// 4. Task-Liste abrufen
async function getTasks() {
const { data, error } = await supabase
.from('tasks')
.select('*')
.order('created_at', { ascending: false });
if (error) throw error;
return data;
}
// 5. Anhang hochladen
async function uploadAttachment(taskId: number, file: File) {
const { data: { user } } = await supabase.auth.getUser();
if (!user) throw new Error('Nicht angemeldet');
const filePath = user.id + '/' + taskId + '/' + file.name;
const { data, error } = await supabase.storage
.from('task-files')
.upload(filePath, file);
if (error) throw error;
// In task_attachments speichern
const { data: attachment, error: dbError } = await supabase
.from('task_attachments')
.insert([
{
task_id: taskId,
file_name: file.name,
file_path: filePath,
file_size: file.size,
}
])
.select();
if (dbError) throw dbError;
return attachment[0];
}
// 6. Task-Anhänge abrufen
async function getTaskAttachments(taskId: number) {
const { data, error } = await supabase
.from('task_attachments')
.select('*')
.eq('task_id', taskId);
if (error) throw error;
// Temporäre Zugriffs-URLs erzeugen
const attachmentsWithURLs = data.map(async (attachment) => {
const { data: urlData } = await supabase.storage
.from('task-files')
.createSignedUrl(attachment.file_path, 3600);
return {
...attachment,
url: urlData.signedUrl,
};
});
return Promise.all(attachmentsWithURLs);
}
// 7. Task abschließen
async function completeTask(taskId: number) {
const { data, error } = await supabase
.from('tasks')
.update({ status: 'completed', updated_at: new Date() })
.eq('id', taskId)
.select();
if (error) throw error;
return data[0];
}
// 8. Abmelden
async function logout() {
await supabase.auth.signOut();
}
Registrierung, Login, Task-CRUD, Datei-Upload – das Grundgerüst einer vollständigen App. Darauf bauen Sie Kategorien, Tags, Kommentare, Benachrichtigungen usw. auf.
Supabase vs. Firebase im Vergleich
Supabase oder Firebase? Hier der direkte Vergleich.
Zentrale Unterschiede
| Vergleichsdimension | Supabase | Firebase |
|---|---|---|
| Datenbanktyp | PostgreSQL (relational) | Firestore (Dokument-NoSQL) |
| Open Source | Vollständig Open Source | Google-Proprietärprodukt |
| Preismodell | Fest $25/Monat (Pro Plan) | Nutzungsbasiert (Read/Write/Storage getrennt) |
| Dateneigentum | 100 % bei Ihnen, jederzeit exportierbar | Daten bei Google, Export umständlich |
| Abfragefähigkeit | Mächtiges SQL, komplexe Joins | Eingeschränkt, komplexe Beziehungen brauchen mehrere Abfragen |
| Echtzeit | WebSocket, manuelles Abonnement | Firestore nativ Echtzeit, automatische Sync |
| Offline | Eigenes Caching nötig | Native Offline-Unterstützung |
| Migration | Standard-PostgreSQL, einfach | Proprietäres Format, hohe Kosten |
Empfehlungen nach Szenario
Supabase wählen, wenn:
- Komplexe Datenbeziehungen und SQL-Abfragen nötig sind
- Langzeitprojekt mit voller Datenkontrolle
- Team kennt SQL und möchte PostgreSQL
- Kostenbewusst – fester Preis stabiler als Nutzungsabrechnung
- Open Source und kontrollierbarer Stack wichtig sind
Firebase wählen, wenn:
- Schneller Prototyp unter Zeitdruck
- Mobile-First, Offline zentral
- Echtzeit-Sync Kernfunktion (Chat, Kollaboration)
- Bereits Google-Cloud-Ökosystem im Einsatz
- Einfache Datenstruktur, wenig komplexe Abfragen
Persönliche Erfahrung: Bei Firebase-Projekten kam die Rechnung einmal auf über $800/Monat. Nach Migration zu Supabase: gleiche Funktionen, etwa $25/Monat – ein großer Unterschied.
Firebase-Datenexport ist mühsam – Firestore-Format ist proprietär, Konvertierung nötig. Supabase: SQL-Export oder CSV über PostgreSQL-Tools – jederzeit Migration zu anderer Datenbank möglich.
Firebase ist bei Echtzeit und Mobile stärker – Firestore-Sync und Offline gut ausgereift. Für Chat oder Kollaborationsdokumente mit starkem Echtzeitbedarf kann Firebase passender sein.
Fazit und Empfehlungen
Supabase im Kern:
- PostgreSQL – mächtige Abfragen, klare Beziehungen
- Enterprise-Authentifizierung – viele Login-Methoden, JWT, RLS
- Objektspeicher – einfach, mit Zugriffskontrolle
- Echtzeit, Edge Functions – zum späteren Vertiefen
Open Source, volle Datenkontrolle, stabile Kosten – wichtig für Langzeitprojekte.
Als Frontend-Entwickler, der schnell Full-Stack bauen will ohne Backend-Konfigurationsstress, ist Supabase eine starke Wahl. Database, Auth und Storage in wenigen Stunden – deutlich schneller als klassische Backend-Entwicklung.
Lernempfehlungen:
- Zuerst Database, Auth und Storage – das Fundament
- Dann RLS-Policies – verbindet Authentifizierung und Berechtigungen
- Bestes Lernmittel: echtes Projekt von Grund auf
- Später Realtime, Edge Functions, Vector Database vertiefen
Die offizielle Dokumentation ist klar geschrieben. Auf GitHub finden Sie awesome-supabase mit vielen Ressourcen.
Kurz: Wenn Sie PostgreSQL als Backend wollen, ohne sich in Konfiguration zu verlieren – Supabase legt den Weg frei. Einfach loslegen.
Supabase – die drei Kernfunktionen schnell einrichten
Supabase-Projekt von Grund auf aufsetzen und Database, Auth sowie Storage beherrschen
⏱️ Estimated time: 2 hr
- 1
Step 1: Supabase-Projekt erstellen
Registrieren Sie sich auf supabase.com und legen Sie ein neues Projekt an:
• Projektname: my-first-app
• Datenbankpasswort: unbedingt notieren
• Region: nächstgelegene wählen (für Asien: Singapore oder Tokyo)
Nach der Erstellung finden Sie unter Settings > API die Project URL und den Anon Public Key - 2
Step 2: Client installieren und initialisieren
Abhängigkeit im Frontend-Projekt installieren:
npm install @supabase/supabase-js
Supabase Client initialisieren:
import { createClient } from '@supabase/supabase-js';
const supabase = createClient(
'https://your-project.supabase.co',
'your-anon-key'
); - 3
Step 3: Datentabelle anlegen und RLS konfigurieren
Tabelle im SQL Editor erstellen:
CREATE TABLE tasks (
id SERIAL PRIMARY KEY,
user_id UUID REFERENCES auth.users(id),
title TEXT NOT NULL,
status TEXT DEFAULT 'pending'
);
ALTER TABLE tasks ENABLE ROW LEVEL SECURITY;
CREATE POLICY 'Users can manage their own tasks'
ON tasks FOR ALL
USING (user_id = auth.uid());
Die RLS-Policy stellt sicher, dass Nutzer nur eigene Daten sehen - 4
Step 4: Benutzerauthentifizierung implementieren
Beispiel für Email/Password-Authentifizierung:
// Registrierung
await supabase.auth.signUp({
email: '[email protected]',
password: 'password123'
});
// Anmeldung
await supabase.auth.signInWithPassword({
email: '[email protected]',
password: 'password123'
});
// Aktuellen Nutzer abrufen
const { data: { user } } = await supabase.auth.getUser();
Social Login über Google, GitHub und 20+ weitere Plattformen unterstützt - 5
Step 5: Dateispeicher konfigurieren
Storage Bucket anlegen (öffentlich oder privat):
// Datei hochladen
await supabase.storage
.from('avatars')
.upload('user-id/avatar.jpg', file);
// Öffentliche URL abrufen
const { data } = supabase.storage
.from('avatars')
.getPublicUrl('user-id/avatar.jpg');
Für private Dateien createSignedUrl für temporäre Zugriffslinks nutzen
FAQ
Was sind die zentralen Unterschiede zwischen Supabase und Firebase?
Für welche Projekte eignet sich Supabase?
• Komplexe Datenbeziehungen mit SQL-Abfragen und Joins
• Langzeitprojekte mit voller Datenkontrolle
• Kostenbewusste Teams mit begrenztem Budget (fester Preis stabiler)
• Frontend-Entwickler, die schnell Full-Stack-Apps bauen
• Open-Source-Priorität und kontrollierbarer Tech-Stack
Was ist Row Level Security (RLS) und wofür braucht man sie?
Welche Anmeldemethoden unterstützt Supabase Auth?
• Email/Password (E-Mail und Passwort)
• Magic Link (passwortlose Anmeldung)
• OTP (Einmalpasswort)
• Social Auth (Google, GitHub, Apple und 20+ Plattformen)
• Phone Auth (Twilio, MessageBird)
• SSO (Enterprise Single Sign-On)
Was ist der Unterschied zwischen öffentlichen und privaten Storage-Buckets?
Wie lange dauert die Migration von Firebase zu Supabase?
Was bietet der kostenlose Supabase-Plan?
14 Min. Lesezeit · Veröffentlicht am: 3. Apr. 2026 · Aktualisiert am: 14. Juli 2026
Supabase in der Praxis
Du liest den ersten Beitrag dieser Serie. Lies den nächsten Beitrag oder öffne die Serienübersicht, um den gesamten Pfad zu sehen.
Vorheriger
Du bist am Anfang dieser Serie.
Nächster
Supabase-Datenbankdesign: Tabellenstruktur, Beziehungen und Row Level Security – vollständiger Leitfaden
Supabase-Datenbankdesign Best Practices: Namenskonventionen, drei Beziehungsmuster, Row Level Security (RLS) und Performance-Optimierung – mit Praxisbeispielen
Teil 2 von 10
Ähnliche Beiträge
Supabase Auth in der Praxis: E-Mail-Verifizierung, OAuth und Session-Management

Supabase Auth in der Praxis: E-Mail-Verifizierung, OAuth und Session-Management
Supabase Storage in der Praxis: Upload, Berechtigungen und CDN-Beschleunigung


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