Zwei Datenbanken, zwei verschiedene Welten
SQLite und PostgreSQL sprechen beide SQL, speichern beide relationale Daten und können beide echte Anwendungen tragen. Darüber hinaus sind sie für unterschiedliche Welten gebaut.
- SQLite ist eine Bibliothek. Sie lebt im Prozess deiner Anwendung und liest eine einzelne
.db-Datei von der Festplatte. Kein Server, kein Port, keine Benutzerkonten zum Konfigurieren. - PostgreSQL ist ein Server. Er läuft als eigener Prozess, hört auf einem Netzwerk-Port und deine Anwendung verbindet sich als Client.
Fast jeder weitere Unterschied – Concurrency, Deployment, Typstrenge, Performance – folgt aus dieser einen architektonischen Aufspaltung. Behalt das im Hinterkopf, während wir uns durcharbeiten.
Architektur: In-Process vs Client/Server
Eine SQLite-Datenbank zu öffnen heißt, eine Datei zu öffnen:
Kein Daemon zum Starten, keine pg_hba.conf zum Editieren, kein Port zum Freigeben. Deine App lädt die SQLite-Bibliothek, öffnet notes.db und feuert Queries. Deployment heißt: "Datei kopieren."
Postgres sieht eher so aus:
# Server starten (einmal, als Admin):
sudo systemctl start postgresql
# Dann aus der App verbinden:
psql -h localhost -U alice -d mydb
Deine Anwendung redet mit einem separaten Prozess – meistens über TCP, manchmal über einen Unix-Socket. Diese Extra-Schicht kostet dich Setup-Zeit und einen Connection-Roundtrip pro Query, bringt dafür aber Netzwerkzugriff, Multi-User-Authentifizierung und echte parallele Schreiber.
Concurrency ist der entscheidende Punkt
Das ist meistens das Argument, das die Wahl entscheidet. SQLite serialisiert Schreibvorgänge: Zu jedem Zeitpunkt hält genau ein Writer einen Lock auf der Datenbankdatei, andere Writer warten. Lesen kann parallel passieren (besonders im WAL-Modus), aber Schreiben läuft strikt nacheinander.
Postgres setzt auf MVCC (Multi-Version Concurrency Control) und Row-Level-Locking. Viele Transaktionen können gleichzeitig auf unterschiedliche Zeilen schreiben, ohne sich gegenseitig zu blockieren.
In der Praxis:
- Ein Blog mit 50 Lesern pro Sekunde und einem gelegentlich schreibenden Autor? SQLite passt locker.
- Ein E-Commerce-Checkout, in dem hunderte Nutzer gleichzeitig den Lagerbestand aktualisieren? Postgres.
- Der lokale Cache einer Mobile-App? SQLite, ohne mit der Wimper zu zucken.
- Ein Multi-Tenant-SaaS-Backend mit Dutzenden Worker-Prozessen? Postgres.
Der WAL-Modus (PRAGMA journal_mode = WAL;) verbessert SQLites Concurrency-Geschichte erheblich – Leser blockieren keine Schreiber mehr –, ändert aber nichts an der Regel "ein Writer zur Zeit".
Typsysteme: Locker vs streng
Postgres ist streng. Eine Spalte, die als INTEGER deklariert ist, weist Strings rigoros zurück:
-- Postgres
CREATE TABLE t (n INTEGER);
INSERT INTO t (n) VALUES ('not a number');
-- ERROR: invalid input syntax for type integer
SQLite arbeitet standardmäßig mit Type Affinity – einer Empfehlung, keiner Regel. Derselbe Insert geht durch:
Der String sitzt jetzt in einer INTEGER-Spalte. SQLite hat ihn als Text gespeichert. Diese Flexibilität war eine bewusste Designentscheidung – nützlich für schnelle Prototypen, gefährlich für langlebige Schemas.
Modernes SQLite (3.37+) unterstützt STRICT-Tabellen, die sich eher wie Postgres verhalten:
Wenn du ein neues SQLite-Projekt anfängst, nimm STRICT. Es eliminiert eine ganze Klasse von "Warum steht in meiner Zahlenspalte ein String?"-Überraschungen.
Featureumfang
Postgres hat von fast allem mehr: Datentypen (Arrays, Ranges, geometrische, Netzwerk, eigene Enums), prozedurale Sprachen (PL/pgSQL, PL/Python), Volltextsuche mit Ranking, materialisierte Views, Tabellen-Partitionierung, Replikation, rollenbasierte Sicherheit und ein riesiges Extension-Ökosystem (PostGIS, TimescaleDB, pgvector).
SQLite deckt das Wesentliche ab und bringt für seine Skala ein paar feine Extras mit: JSON-Funktionen, Volltextsuche per FTS5, R-Tree-Indizes, Window Functions, CTEs, generierte Spalten. Was es weglässt, ist alles, was einen Server voraussetzt: Benutzer, Rollen, Replikation, Netzwerkzugriff.
Eine grobe Faustregel:
- GIS, Vektorsuche oder Replikation gebraucht? Postgres.
- Datenbank in eine iOS-App ausliefern? SQLite.
- Beides? Viele Teams entwickeln und testen gegen SQLite und deployen auf Postgres – obwohl dich diese Mischung an Syntaxunterschieden beißen kann (siehe unten).
Syntaxunterschiede, die du tatsächlich treffen wirst
Das meiste alltägliche SQL ist identisch. Die Unterschiede konzentrieren sich auf Schema, Typen und ein paar eingebaute Funktionen:
-- Auto-incrementing Primary Key
-- SQLite:
CREATE TABLE users (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT);
-- Postgres:
CREATE TABLE users (id SERIAL PRIMARY KEY, name TEXT);
-- oder, modernes Postgres:
CREATE TABLE users (id INTEGER GENERATED ALWAYS AS IDENTITY PRIMARY KEY, name TEXT);
-- Aktueller Timestamp
-- SQLite: CURRENT_TIMESTAMP (liefert Text)
-- Postgres: NOW() (liefert Timestamp)
-- Boolean-Typ
-- SQLite: kein echtes BOOLEAN; INTEGER 0/1 verwenden
-- Postgres: BOOLEAN mit TRUE/FALSE
Wenn du auf SQLite entwickelst und auf Postgres deployst, lohnt sich ein ORM oder ein Migrations-Tool als Schicht zwischen dir und dem rohen SQL – sonst sickern diese Unterschiede direkt in deine App.
Performance, ehrlich
"Schneller" hängt von der Frage ab. Für einen einzelnen Prozess, der liest und kleine Writes macht, ist SQLite kaum zu schlagen – kein Netzwerkhop, kein Protokoll-Parsing, keine Client-Verbindung. In Benchmarks mit einem einzigen Client läuft SQLite Postgres bei einfachen Queries oft davon.
Pack parallele Schreiber dazu, große Datasets, die parallele Query-Ausführung wollen, oder komplexe Query-Pläne, die vom ausgereiften Postgres-Planner profitieren – und Postgres zieht vorbei. Postgres skaliert außerdem vertikal (größere Maschinen, mehr Cores) auf eine Art, für die SQLite schlicht nicht designt ist.
Die ehrliche Zusammenfassung: SQLite ist schnell für das, wofür es gemacht ist. Postgres ist schnell für das, wofür es gemacht ist. Wähl nach Workload-Form, nicht nach Benchmark-Schlagzeilen.
Eine kurze Entscheidungshilfe
Greif zu SQLite, wenn:
- Die Daten neben einer einzelnen Anwendung liegen – Desktop, Mobile, Embedded, CLI-Tool.
- Schreibvorgänge aus einem einzigen oder einer kleinen Zahl von Prozessen kommen.
- Du Zero-Configuration-Deployment willst.
- Du prototypisierst und dich auf das Schema konzentrieren willst, nicht auf Infrastruktur.
Greif zu Postgres, wenn:
- Mehrere Application-Server oder Worker in die Datenbank schreiben.
- Du Netzwerkzugriff von vielen Clients brauchst.
- Du fortgeschrittene Features willst: Rollen, Replikation, GIS, eigene Typen, Stored Procedures.
- Die Daten der dauerhafte, zentrale Speicher eines produktiven Dienstes sind.
Ein häufiger Weg: Klein anfangen mit SQLite, auf Postgres wechseln, sobald die Traffic-Form es verlangt. Die Migration ist nicht gratis, aber ein bekannter Vorgang – und die meisten Projekte kommen nie an diesen Punkt.
Als Nächstes: Wann SQLite die richtige Wahl ist
Der Vergleich oben gibt dir die Trade-offs an die Hand. Die nächste Seite geht tiefer auf den positiven Fall ein – die Workloads, in denen SQLite nicht nur gut genug ist, sondern tatsächlich das bessere Werkzeug, und die Warnsignale, die dir sagen, dass du es entwachsen bist.
Häufig gestellte Fragen
Was ist der wichtigste Unterschied zwischen SQLite und Postgres?
SQLite ist eine eingebettete Bibliothek, die eine einzige Datei direkt im Prozess deiner Anwendung liest und schreibt. PostgreSQL ist ein eigenständiger Server, mit dem du dich übers Netzwerk verbindest. Aus diesem einen architektonischen Unterschied folgen praktisch alle weiteren Vergleichspunkte – Concurrency, Deployment, Typen und Tooling hängen alle daran.
Ist SQLite schneller als Postgres?
Bei Lesezugriffen aus einem einzigen Prozess und kleinen Schreibvorgängen oft ja – SQLite hat keinen Netzwerk-Roundtrip und keinen Overhead durch ein Client/Server-Protokoll. Bei vielen gleichzeitigen Schreibern aus mehreren Clients zieht Postgres dank Row-Level-Locking und MVCC vorbei. 'Schneller' hängt am Workload, nicht an der Engine.
Kann ich SQLite produktiv einsetzen?
Ja, für die richtigen Workloads. SQLite betreibt produktiv Webseiten, Desktop-Apps und Embedded-Geräte ohne Probleme. Die Grenze sind parallele Schreiber: Wenn viele Prozesse gleichzeitig schreiben müssen, geht das in Postgres nativ, während SQLite Schreibvorgänge serialisiert. WAL-Modus mildert das, hebt das Limit aber nicht auf.
Wie migriere ich von SQLite zu Postgres?
Schema und Daten mit sqlite3 mydb.db .dump exportieren, dann das SQL anpassen – AUTOINCREMENT wird zu SERIAL oder GENERATED AS IDENTITY, Typnamen ändern sich und ein paar SQLite-Eigenheiten wie das lockere Typsystem brauchen Nachbearbeitung. Tools wie pgloader automatisieren den größten Teil. Plan ein, alles umzuschreiben, was sich auf SQLites flexibles Typsystem verlassen hat.