Datenbank-Wahl für Webprojekte: Postgres vs. MySQL vs. SQLite – realistische Use Cases

Postgres vs. MySQL vs. SQLite

Du brauchst keine “beste DB”. Du brauchst die DB, die zu Traffic, Team und Hosting passt – ohne dass du in 6 Monaten deine eigene Entscheidung verfluchst.

Die meisten DB-Entscheidungen scheitern nicht an Features. Sie scheitern an falschen Erwartungen: “Wir werden viral”, “Wir brauchen sofort HA”, “SQLite ist nur für Spielzeug” oder “Postgres ist immer besser”.

Hier ist der Deal: Postgres, MySQL und SQLite sind alle legit. Aber sie sind für unterschiedliche Realitäten gebaut: Client-Server vs. embedded, viele gleichzeitige Schreiber vs. “ein Writer reicht”, Ops-Aufwand vs. Null-Konfig.

Wir machen das pragmatisch: erst Use Cases, dann Entscheidung. Mit Tabelle, Checkliste und den typischen “Tränen-in-Prod”-Momenten.

Erst Use Case, dann DB: 6 Fragen, die wirklich zählen

  1. Write-Profil: Schreibst du selten (Admin-Tool) oder ständig (Events, Chats, Telemetrie)?
  2. Concurrency: Wie viele gleichzeitige Nutzer schreiben realistisch gleichzeitig?
  3. Ops-Budget: Hast du Bock auf DB-Admins, Tuning, Backups, Monitoring – oder soll das “einfach laufen”?
  4. Deployment-Form: Klassischer Server, Managed DB, Container, Edge/Single-Node, Offline/Local?
  5. Query-Komplexität: Simple CRUD oder Reporting, Joins, JSON, Volltext, Aggregationen?
  6. Lizenz/Distribution: Willst du DB in ein Produkt “einbetten” und verteilen (SQLite easy), oder nur als Service betreiben (dann sind Lizenzen meist entspannt)?

Postgres: wenn “einfach nur CRUD” nicht mehr reicht

Warum Postgres in echten Webprojekten oft gewinnt

Postgres ist stark, wenn du viele parallele Zugriffe hast und trotzdem konsistent bleiben willst. Intern nutzt Postgres ein Multiversion-Modell (MVCC), damit Abfragen einen konsistenten “Snapshot” sehen, während parallel geschrieben wird. Das ist genau die Art Feature, die du erst vermisst, wenn’s knallt.

Realistische Use Cases für Postgres

  • SaaS mit Teams & Rollen: viele Tabellen, viele Joins, konsistente Rechte, Audit Logs.
  • Reporting-lastige Apps: Aggregationen, “letzte 30 Tage”, Cohorts, Dashboards.
  • Mixed Data: relational + JSON-Felder (z.B. flexible Settings) – ohne gleich NoSQL zu spielen.
  • Wachsende Systeme: du willst Optionen wie logische Replikation/Read-Replikas später dazunehmen.

MySQL: der pragmatische Standard (und das ist keine Beleidigung)

Warum MySQL in vielen Projekten völlig reicht

MySQL ist in der Praxis oft “die DB, die einfach überall läuft”. Mit InnoDB bekommst du Transaktionen, ACID-Verhalten, Row-Level-Locking und solide Concurrency-Mechaniken. Für sehr viele Webapps ist das schon 95% der Miete.

Realistische Use Cases für MySQL

  • Content/Commerce/CRUD-Apps: klassische Datenmodelle, viele Standard-Queries.
  • Hosting-Realität: Shared Hosting oder günstige Managed-Angebote, wo MySQL “out of the box” da ist.
  • Teams mit MySQL-Erfahrung: du sparst Zeit, weil Leute wissen, wie’s läuft.
  • Skalierung mit klaren Patterns: Read-Replikas, Caching, saubere Indizes – ohne Experimentierwiese.

SQLite: brutal praktisch – wenn du seine Grenzen akzeptierst

Was SQLite eigentlich ist

SQLite ist keine “kleine MySQL”. Es ist eine embedded, serverlose Datenbank als Library: self-contained, zero-configuration, transactional. Du packst sie in deine App, fertig. Das macht sie genial für lokale Daten, Edge-Deployments oder Single-Node Webapps.

Concurrency ehrlich erklärt (WAL hilft, aber zaubert nicht)

Mit Write-Ahead Logging (WAL) können Reader und Writer gleichzeitig laufen. Aber: es gibt nur einen Writer zur Zeit. Das ist keine Meinung, das ist Design. Wenn deine App viele parallele Writes braucht, bekommst du Locking/Busy-Themen – und dann wird’s unromantisch.

Realistische Use Cases für SQLite im Web

  • Single-Node Apps: interne Tools, kleine Produkte, Admin-Dashboards, Prototypen, MVPs.
  • Edge/Offline/Local-first: Daten nahe am Nutzer oder im Client/Device-Context.
  • Queues/Job-Metadaten: wenn Write-Rate moderat ist und du “no ops” willst.
  • Dev/Test: schnelle lokale Umgebung, reproduzierbar, ohne DB-Setup.

Vergleichstabelle: welche DB passt zu welchem Web-Use-Case?

Kriterium Postgres MySQL SQLite
Deployment Client-Server, ideal mit Managed DB Client-Server, sehr verbreitet bei Hostern Embedded (Library), Datei-basiert
Concurrency (Writes) stark bei parallelen Workloads (MVCC) solide (InnoDB Transaktionen/Locks) ein Writer zur Zeit; WAL verbessert Reader/Writer parallel
Ops-Aufwand mittel (Tuning/Backups/Monitoring) mittel (aber oft “bekannt & standardisiert”) niedrig (aber Backups & Locking verstehen!)
Typische Web-Use-Cases SaaS, Reporting, komplexe Domain-Modelle CRUD, CMS, Shops, Standard-Backends Single-Node, Edge, lokal/offline, MVP
Lizenz (Kurzfassung) permissiv (PostgreSQL License) Community unter GPL, außerdem kommerzielles Dual-Licensing Public Domain

So setzt du’s um

7-Schritte-Plan: DB wählen ohne Architektur-FOMO

  1. Schreibprofil messen oder schätzen: “Wie viele Writes pro Sekunde” und “wie parallel” – grob reicht.
  2. Single-Node oder verteilt? Wenn du eh nur einen Node hast: SQLite kann ernsthaft reichen.
  3. Wähle die kleinste DB, die sicher passt: nicht “was kann am meisten”, sondern “was löst mein Problem stabil”.
  4. Plane Backups/Restore zuerst: nicht optional. Restore testen, sonst ist’s kein Backup.
  5. Indizes & Query-Plan Basics: egal welche DB – ohne Indizes ist alles langsam.
  6. Connection Handling: Server-DBs brauchen sauberes Pooling; SQLite braucht saubere Schreib-Serialisierung.
  7. Exit-Strategie: Schema-Migrations + Datenexport so halten, dass ein Wechsel später möglich bleibt.

Mini-Use-Case Cheatsheet

  • Agentur-Webapp mit 5–50 Kundenprojekten: MySQL oder Postgres, je nach Team/Hosting. SQLite nur, wenn Single-Node + moderate Writes.
  • SaaS mit Teams, Rollen, Audits: Postgres (du willst die Reserven).
  • Edge-Tool / lokale Desktop-App / Offline-first: SQLite (dafür ist es gebaut).
# SQLite: WAL aktivieren (wenn sinnvoll)
PRAGMA journal_mode = WAL;

# Reminder:
# WAL hilft bei parallelem Lesen/Schreiben,
# aber es bleibt ein Writer zur Zeit.

Typische Fehler & wie du sie vermeidest

  • Fehler: SQLite für hoch-parallele Write-Workloads. Fix: Wenn viele Writes gleichzeitig: Server-DB (Postgres/MySQL) oder Write-Queue/Serialisierung.
  • Fehler: “Wir nehmen Postgres, weil Profi.” Fix: Wenn dein Hosting/Team/MySQL-Stack eingespielt ist: MySQL ist oft die schnellere, billigere Realität.
  • Fehler: Keine Restore-Tests. Fix: Monatlich einmal: Backup einspielen und prüfen (sonst merkst du den Fehler erst im Desaster).
  • Fehler: Schema driftet ins Chaos (besonders bei JSON). Fix: Regeln definieren: welche Felder sind relational, welche flexibel.
  • Fehler: “DB ist langsam” ohne Messung. Fix: Slow Query Logs, EXPLAIN/Query Plan, Index-Check. Meist ist es ein Query/Index-Problem, kein “DB-Problem”.

Fazit: die pragmatische Empfehlung

Wenn du unsicher bist und “normale” Webapps baust: MySQL oder Postgres sind beide safe. Nimm das, was dein Team besser kann und was dein Hosting sauber unterstützt.

Wenn du erwartest, dass Queries/Reporting/Constraints komplex werden: Postgres gibt dir mehr Reserven und gute Werkzeuge für Concurrency und Datenmodellierung.

Wenn du Single-Node/Edge/Local-first bist: SQLite ist nicht zweite Wahl, sondern oft die richtige – solange du das Single-Writer-Modell respektierst.

Nächster Schritt: Schreib 3 echte Queries aus deinem Projekt auf (die wichtigsten). Dann entscheide anhand von Concurrency + Ops-Budget. Das ist 10x besser als “DB-Tier-Lists”.

FAQ

Für viele Projekte sind beide top. Postgres ist oft stärker bei komplexeren Datenmodellen und Concurrency-Workloads (MVCC). MySQL ist extrem verbreitet, pragmatisch zu hosten und mit InnoDB solide für die meisten CRUD-Apps.

Wenn du Single-Node fährst, wenig Ops willst, lokal/offline arbeitest oder Edge-nahe Datenhaltung brauchst. SQLite ist embedded und super schnell für viele “kleine bis mittlere” Workloads.

WAL hilft massiv, weil Reader/Writer parallel laufen können. Aber es bleibt dabei: es gibt nur einen Writer zur Zeit. Mehrere Nutzer gehen klar, solange deine Write-Parallelität moderat ist oder du Writes sauber serialisierst.

MVCC (Multiversion Concurrency Control) bedeutet grob: Leser sehen einen konsistenten Snapshot, während parallel geschrieben wird. Das reduziert Konflikte zwischen Reads und Writes und macht Postgres in multi-user Szenarien stark.

MySQL ist bei Hostern oft “Standard an Bord”. Postgres ist als Managed DB ebenfalls sehr gut verfügbar. SQLite ist am einfachsten, wenn du Single-Node fährst: keine Server-Installation, aber du musst Backups, File-Locking und Deployment-Details sauber lösen.

Postgres ist permissiv lizenziert (ähnlich BSD/MIT). MySQL Community ist GPL und wird zusätzlich kommerziell dual-lizenziert. SQLite ist Public Domain. Für die meisten Webapps als Service ist das selten ein Showstopper, aber bei “DB einbetten und verteilen” wird’s relevanter.

Overkill (zu früh), falsche Annahmen über Write-Parallelität (SQLite), ignorierte Backups/Restore-Tests, und “Performance-Tuning ohne Messung”. Die DB ist selten das Problem – oft sind es Queries, Indizes oder Ops.