Geschrieben von Huifer, Solo-Entwickler und Maintainer von TanStack Ship. Ich betreibe Cloudflare D1 seit 18 Monaten in vier produktiven SaaS-Apps (maximal 2.400 Zeilen bei der größten) und Postgres-on-Neon in drei produktiven B2B-Apps (maximal 11M Zeilen bei der größten). Dies ist der ehrliche D1 vs Postgres-Vergleich, den ich mir vor meiner ersten App gewünscht hätte: reale Produktionslimits, echte Produktionspreise, eine auf die SaaS-Struktur abgestimmte Entscheidungsmatrix und ein ehrlicher Migrationspfad. Kein Sponsoring durch Anbieter; jede Behauptung verlinkt auf eine Primärquelle.
Verifizierte Quellen: Cloudflare D1 docs · D1 limits · D1 best practices · D1 pricing · Neon serverless Postgres · Neon pricing · PostgreSQL official docs · SQLite query planner · Workers Analytics Engine · Drizzle ORM D1 driver · Zuletzt aktualisiert: 09. Mai 2026 · Changelog
TL;DR: D1 ist der richtige Standard für eine Workers-native, leseintensive SaaS im Jahr 2026: Sub-Millisekunden-Lesezugriffe von regionalen Replicas, kein Connection Pool, den man verwalten muss, der SQLite's Query Planner und nur eine einzige Abrechnungsposition. Postgres-on-Neon ist die richtige Wahl, wenn Sie
JSONB,LISTEN/NOTIFY, sofort einsatzbereite Volltextsuche oder Datenbanken über>10 GBbenötigen. Beide haben ehrliche Limits — die 10 GB Datenbank-Grenze und Write-Lock Contention bei D1; der ~1,2 s Kaltstart und Egress-Kosten bei regionenübergreifenden Lesezugriffen bei Neon. Der Artikel endet mit einer Entscheidungsmatrix und einem ehrlichen Migrationspfad. Wenn Sie zuerst die detaillierten Benchmarks sehen möchten, lesen Sie den Beitrag D1 performance for SaaS post; für Produktionsmuster sehen Sie sich den D1 production guide an.
Cloudflare D1 vs Postgres: Der 18-monatige Produktionsvergleich
Auf die Frage "D1 vs Postgres" gibt es keine einzige richtige Antwort, aber eine kleine Anzahl ehrlicher. Cloudflare D1 ist eine davon; Neon Serverless Postgres ist die andere, die ich tatsächlich bei produktiven B2B-Anwendungen einsetze. Beide Engines werden zunächst für ihre größten Stärken anerkannt, dann dort gezeigt, wo sie tatsächlich verlieren, mit einer Entscheidungsmatrix und einem Migrationspfad am Ende.
Die Datenbankentscheidung für die Produktion im Jahr 2026
Zwei Entwicklungen haben in den letzten drei Jahren die Datenbanklandschaft für Solo-SaaS-Gründer neu geformt. Edge-Runtimes – allen voran Cloudflare Workers – haben die Rechenleistung nah an die Nutzer gebracht. SQLite hat sich zu einem Baustein für verteilte Systeme entwickelt, wobei D1 eine Einzeldatei-Engine in eine global replizierte Datenbank mit Sub-Millisekunden-Lesezugriffen verwandelt hat.
Für einen SaaS-Gründer auf Workers ist D1 der Standard und Postgres ist das Migrationsziel – nicht, weil Postgres "älter" ist, sondern weil die beiden Engines unterschiedliche Problemstellungen zu unterschiedlichen Preispunkten lösen. Der folgende Vergleich basiert auf dem parallelen Betrieb beider Engines mit bezahltem SaaS-Traffic.
Cloudflare D1: Die Edge-SQLite Wette
D1 ist SQLite 3.46+ mit HTTP-basierten Bindings, automatischen Backups zu Cloudflare R2 und Read Replicas in jeder Region, in der Cloudflare vertreten ist.
Stärken: Wo D1 gewinnt
Die vier Produktionsvorteile von D1 haben sich in allen meinen vier Deployments bewährt:
Edge-Latenz, Zero Pool
Ein D1-Lesezugriff von einem Worker in derselben Region geschieht in Sub-Millisekunden. Es gibt keinen Connection Pool — jeder Worker-Aufruf ist ein einzelnes, kurzlebiges SQLite-Open, das sich beim Ende des Requests schließt. Dieses Muster gilt sowohl für kalte als auch für warme Worker.
Vorhersehbare Abrechnung
Die D1 pricing beläuft sich auf $0,75/GB-Monat für gespeicherte Zeilen und beinhaltet pro Account ein kleines Kontingent inklusiver Lese-/Schreibvorgänge. Keines meiner vier D1-Deployments hat jemals signifikante Speicherkosten verursacht; die Kosten für die Requests sind der einzige Posten, der sich bewegt.
SQLite-Tools überall
Dasselbe sqlite3 CLI, das Sie lokal ausführen, funktioniert auch gegen ein D1-Backup. Der SQLite query planner ist der schnellste Query Planner, den ich für leseintensives OLTP gemessen habe. Geben Sie sqlite3 my.db ein und Sie sind drin.
Keine Egress-Kosten
Regionenübergreifende Replica-Lesezugriffe sind innerhalb des Workers-Ökosystems kostenlos. Das verändert die Unit-Economics für jedes Feature, das sich geografisch ausbreitet — mandantenfähige Dashboards, länderspezifische Preise, Suchindizes pro Region.
Limits: Wo D1 tatsächlich verliert
10 GB Datenbank-Grenze
Laut den D1 limits ist eine einzelne D1-Datenbank auf 10 GB beschränkt. Bei B2C mit Medienkatalogen spielt das eine Rolle; bei B2B fast nie. Die Grenze gilt für die Datenbankgröße, nicht für das Working Set, ein schlankeres Schema mit archivierten Zeilen kann sich also problemlos auf weit über 50 Millionen Zeilen strecken.
Write-Lock Contention
Eine einzelne D1-Datenbank serialisiert Schreibvorgänge durch einen einzelnen Writer. Anhaltende schreibintensive Workloads (>50 Writes/Sekunde aggregiert) führen zu einem Latenz-Tail und einer Queue-Tiefe am Writer. Die Gegenmaßnahme sind die D1 best practices on batching — fassen Sie Schreibvorgänge in weniger Aufrufe zusammen, nicht in mehr.
Kein JSONB, kein LISTEN/NOTIFY
SQLite JSON1 ist gut, aber kein Postgres JSONB. Wenn der Wert Ihres Schemas von GIN-Indizes über verschachtelte Objekte abhängt, gewinnt Postgres. Das Gleiche gilt für LISTEN/NOTIFY-Change-Feeds — D1 hat kein natives Äquivalent.
Keine vergleichbare native Volltextsuche
FTS5 in SQLite funktioniert, erfordert aber ein explizites Setup und ist nicht auf Augenhöhe mit tsvector + pg_trgm. Die Qualität des Rankings bei mehrsprachigen Textkorpora ist bei Postgres wesentlich besser.
Postgres (Neon): Der Serverless Postgres Prime
Postgres auf Neon ist die klassische Wahl für "Postgres ohne VM-Verwaltung". Volles Postgres 16+; die Runtime trennt Rechenleistung von Speicherplatz, sodass die Datenbank im Leerlauf auf null skaliert.
Stärken: Wo Postgres gewinnt
Die vier Produktionsvorteile von Postgres gegenüber D1 haben sich in allen meinen drei Neon-Deployments bestätigt:
Die volle SQL-Oberfläche
JSONB mit GIN-Indizes, tsvector Volltextsuche, LISTEN/NOTIFY für Change-Feeds, Window-Functions, Lateral Joins — alles, was Sie im Standard-Postgres schreiben können, funktioniert. Das ist der wichtigste alleinige Grund, warum B2B-SaaS zu Postgres migriert.
Skalierung über das D1-Limit hinaus
Die Neon free tier skaliert auf 0,5 GB; der kleinste kostenpflichtige Plan bewältigt 100 GB+. Die Größte in meinem Portfolio ist eine Tabelle mit 11M Zeilen an Events, die seit 14 Monaten einwandfrei läuft.
Postgres-native Tools
Das psql CLI verhält sich wie erwartet. pg_dump und pg_restore erzeugen Dumps, die mit jedem Postgres 16-Host, on-prem oder anderweitig, kompatibel sind. Debugging ist deterministisch.
Ausgereifte Extensions
pg_trgm, pgvector, pg_cron, PostGIS — das Extension-Ökosystem von Postgres ist das langlebigste in der OLTP-Welt.
Limits: Wo Postgres tatsächlich verliert
Kaltstart-Latenz
Eine Neon-Datenbank, die für 5+ Minuten im Leerlauf war, benötigt beim ersten Query ~1,2 Sekunden, um aufzuwachen. Auto-Scaling hilft; Kaltstarts bleiben jedoch der längste Latenz-Tail im Budget. Ein kostengünstiger "Pinger"-Worker, der alle 4 Minuten einen No-Op-Query absetzt, kostet $0,02/Monat mehr, beseitigt aber diese Spitze.
Egress-Kosten
Regionenübergreifende Lesezugriffe laufen durch den Neon-Proxy und verursachen Egress-Gebühren. Keines meiner Deployments erreichte jemals eine signifikante Egress-Rechnung, aber die Rate ist ungleich null und sollte im Voraus budgetiert werden.
Connection Pool Overhead
Selbst bei Neon Serverless benötigt jeder Worker, der auf Postgres zugreift, einen Pool auf Treiber-Ebene. Für Workers im Speziellen ist Cloudflare Hyperdrive das richtige Muster, fügt aber dem Produktions-Stack eine weitere bewegliche Komponente hinzu.
JSONB ist nicht kostenlos
JSONB ist großartig, aber der Missbrauch von GIN-Indizes darauf ist das langsamste Schema-Pattern, das Postgres hat. Vergleichen Sie JSONB-Queries mit relationalen, bevor Sie sich festlegen.
Entscheidungsmatrix: D1 vs Postgres nach SaaS-Struktur
Acht Zeilen, drei Spalten. Die erste Spalte beschreibt das Workload-Profil, die zweite die empfohlene Engine, die dritte den ehrlichen Grund.
| Workload-Struktur | Empfohlene Engine | Warum |
|---|---|---|
| Leseintensive SaaS, < 10M Zeilen, Workers-nativ | D1 | Sub-Millisekunden-Lesezugriffe, Zero Pool, eine einzige Abrechnungsposition |
| Schreibintensive SaaS, < 50 Writes/Sekunde | D1 | Ein einzelner Writer reicht aus; > 50 Writes/Sekunde und Sie spüren den Lock |
Schema mit JSONB oder GIN-indizierten Objekten | Postgres | SQLite JSON1 ist das falsche Tool für tiefe Objekt-Queries |
| Volltextsuche bei User-Content | Postgres | tsvector + pg_trgm schlagen FTS5 bei Setup-Kosten und Ranking-Qualität |
| Echtzeit-Change-Feed zu Clients | Postgres | LISTEN/NOTIFY ist ein Query; auf D1 müssen Sie es manuell verdrahten |
>10 GB Datenbank oder B2C-Medienkatalog | Postgres | Jenseits der 10 GB D1-Grenze; Neons kleinster Plan bewältigt das |
| Kaltstart-empfindliche User-Facing API | D1 | Sub-Millisekunden-Lesezugriffe schlagen 1,2 s Neon-Kaltstart bei gleichem Query |
| Regionenübergreifender Fan-Out, geringe Schreibrate | D1 | Kostenlose regionenübergreifende Reads schlagen Neons Egress beim gleichen Workload |
Die Matrix lässt sich auf zwei Regeln reduzieren: Wenn das Workload-Profil in SQLite passt und Sie auf Workers laufen, wählen Sie D1. Alles andere migriert zu Postgres.
Wann Sie von D1 zu Postgres migrieren sollten
Die Migrations-Trigger, die ich in der Produktion verwendet habe, in absteigender Priorität:
Datenbankgröße nähert sich 10 GB
Wenn rows + indexes 60 % der 10 GB cap (~6 GB) überschreitet, starten Sie einen Postgres-Sidecar — D1-Reads bleiben live, während Postgres neue Writes übernimmt. Den Datenteil finden Sie im Beitrag D1 backup and restore.
Write Contention taucht im Latenz-Tail auf
Wenn die p99 Write-Latenz dauerhaft 250 ms überschreitet, ist der Lock der Flaschenhals. Postgres-on-Neon mit einem Pool verarbeitet denselben Schreib-Load mit 30–50 ms p99.
Neues Feature erfordert JSONB, FTS oder LISTEN/NOTIFY
Der sauberste Auslöser. Bauen Sie das neue Feature ab dem ersten Tag auf Postgres; der Rest der App bleibt auf D1, bis zur nächsten Migration. Die meisten B2B-Apps verbleiben für 6–12 Monate in diesem "polyglotten" Zustand.
Compliance-Vorgaben erfordern Postgres-Verschlüsselungsmodule
Einige regulierte Branchen (HIPAA, bestimmte EU-Workloads) erfordern Postgres' Row-Level Security oder pgcrypto auf der Datenbankebene. D1 bietet beides nicht. Als Auslöser bei Solo-SaaS selten, taucht aber in B2B-Verkaufsgesprächen auf.
Ein durchgearbeitetes Produktionsbeispiel
Gleiches Schema, zwei Engines. Der Query gibt "Teilnehmer (Tenants) mit dem jüngsten bezahlten Event" zurück:
D1 Schema und Query
-- D1: SQLite-Dialekt, tenant_id zuerst, Integers für die Zeit
CREATE TABLE projects (
id TEXT PRIMARY KEY,
tenant_id TEXT NOT NULL,
name TEXT NOT NULL,
created_at INTEGER NOT NULL DEFAULT (unixepoch())
);
CREATE INDEX idx_projects_tenant_created
ON projects(tenant_id, created_at DESC);
CREATE TABLE events (
id TEXT PRIMARY KEY,
tenant_id TEXT NOT NULL,
kind TEXT NOT NULL,
amount_cents INTEGER NOT NULL,
created_at INTEGER NOT NULL DEFAULT (unixepoch())
);
CREATE INDEX idx_events_tenant_kind_created
ON events(tenant_id, kind, created_at DESC);
-- Der Query
SELECT
p.tenant_id,
p.name,
MAX(e.created_at) AS latest_paid_at
FROM projects p
JOIN events e
ON e.tenant_id = p.tenant_id
WHERE e.kind = 'paid'
GROUP BY p.tenant_id, p.name
ORDER BY latest_paid_at DESC
LIMIT 10;
Postgres-on-Neon Schema und Query
-- Postgres: echtes TIMESTAMPTZ, JSONB wird unterstützt
CREATE TABLE projects (
id TEXT PRIMARY KEY,
tenant_id TEXT NOT NULL,
name TEXT NOT NULL,
metadata JSONB NOT NULL DEFAULT '{}'::jsonb,
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
CREATE INDEX idx_projects_tenant_created
ON projects(tenant_id, created_at DESC);
CREATE TABLE events (
id TEXT PRIMARY KEY,
tenant_id TEXT NOT NULL,
kind TEXT NOT NULL,
amount_cents INTEGER NOT NULL,
payload JSONB NOT NULL DEFAULT '{}'::jsonb,
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
CREATE INDEX idx_events_tenant_kind_created
ON events(tenant_id, kind, created_at DESC);
-- Derselbe Geschäfts-Query, mit vollem JSONB-Zugriff und FILTER
SELECT
p.tenant_id,
p.name,
MAX(e.created_at) AS latest_paid_at,
SUM(e.amount_cents) FILTER (WHERE e.kind = 'paid') AS total_paid_cents
FROM projects p
JOIN events e
ON e.tenant_id = p.tenant_id
WHERE e.kind = 'paid'
GROUP BY p.tenant_id, p.name
ORDER BY latest_paid_at DESC
LIMIT 10;
Die gleiche Query-Struktur, aber Postgres liefert Ihnen FILTER, echtes TIMESTAMPTZ und JSONB kostenlos. D1 hält Sie bei INTEGER Unix-Timestamps und zwingt Sie dazu, die FILTER-Arbeit im Application Code vorzunehmen. Mit Drizzle ORM kompiliert dieselbe TypeScript Schema-Definition für beide Dialekte.
Wo jede Engine ehrlich gewinnt
Vor dem Call-to-Action noch die eindeutigen Fälle:
- D1 gewinnt bei Workers-nativen, leseintensiven SaaS. Sub-Millisekunden Edge-Lesezugriffe, kein Connection Pool, vorhersehbare Abrechnung — vier kostenpflichtige Produkte in meinem eigenen Portfolio.
- D1 gewinnt bei regionenübergreifenden Fan-Out-Workloads. Kostenlose regionenübergreifende Replica-Lesezugriffe ohne Egress-Kosten sind ein Unit-Economics-Vorteil, den Postgres-on-Neon nicht erreichen kann.
- Postgres gewinnt bei schema-lastigen Analysen. Wenn die Geschäftsstruktur von
JSONB,tsvector,LISTEN/NOTIFYoder einer der 200+ Postgres-Extensions profitiert, machen sich die Migrationskosten durch das saubere Schema bezahlt. - Postgres gewinnt bei
>10 GBoder schreibintensiven Workloads. Jenseits der 10 GB D1-Grenze oder der 50-Writes/Sekunde-Deckelung ist Postgres-on-Neon oder ein anderes Managed Postgres der operativ einfachere Weg.
Wo TanStack Ship ins Spiel kommt: Ein Solo-Entwickler, der D1 als Standard mit einem Postgres-bereiten Stack möchte — Schema-Patterns, Drizzle ORM Migrationen und der dokumentierte Migrationspfad sind alle bereits integriert. TanStack Ship rüstet D1 mit dem gleichen First-Class-Erlebnis aus, das Sie auch von Postgres erwarten würden, einschließlich drizzle.config.ts, dem Migration-Runner und der obigen Matrix als Runbook.
FAQ
Ist D1 im Jahr 2026 produktionsbereit?
Ja, für leseintensive Workloads unterhalb der 10 GB cap. Alle meine vier produktiven D1-Deployments laufen seit 18+ Monaten mit einer gemessenen Downtime, die unter der Cloudflare Workers SLA liegt. Schreibintensive Workloads mit mehr als 50 Writes/Sekunde profitieren nach wie vor von Postgres.
Wie schneidet D1 preislich im Vergleich zu Postgres ab?
Gemäß dem D1 pricing und Neon pricing kostet eine 1 GB D1 Datenbank mit 5M monatlichen Leseanfragen ca. $0,75/Monat Speicher + $0,05/Monat Reads ≈ $0,80/Monat. Derselbe Workload beim Neon Launch ist $0/Monat, bis Sie das Free-Tier verlassen, dann $19/Monat. Für wenig schreibintensive Workloads ist D1 wesentlich günstiger; für schreibintensive Anwendungen oder riesige Datenbanken gewinnt Neon.
Kann D1 automatisch global replizieren?
Ja, über das Feature D1 read replicas. Writer sind global auf einen Primary beschränkt; Reader fächern sich in jede Cloudflare-Region auf. Das ist der größte Unterschied in den Unit-Economics zwischen D1 und Postgres-on-Neon für regionenübergreifenden Traffic.
Was passiert mit meiner TanStack Start App, wenn D1 die 10 GB Grenze erreicht?
Die Query-Lage liefert weiterhin Ergebnisse; neue Schreibzugriffe schlagen fehl mit StorageLimitExceeded. Der Recovery-Pfad ist ein Postgres-Sidecar, das neue Schreibzugriffe übernimmt, während D1 auf Read-Only bleibt — den Datenteil finden Sie im Beitrag D1 backup and restore. Bei keiner meiner Apps in der Produktion ist das bislang aufgetreten, aber das Runbook ist durchgeprobt.
Unterstützt D1 Transaktionen über mehrere Tabellen hinweg?
Ja — jede D1-Query befindet sich pro Worker-Aufruf automatisch innerhalb einer Transaktion, wenn Batch-Statements gemäß den D1 best practices genutzt werden. Cross-Request-Transaktionen erfordern db.batch([...]) und laufen auf demselben Write-Lock.
Wann sollte ich Postgres gegenüber D1 für eine brandneue SaaS bevorzugen?
Wenn das Schema JSONB, Volltextsuche oder LISTEN/NOTIFY benötigt, oder prognostiziert wird, dass es in den ersten 12 Monaten die 10 GB überschreitet, beginnen Sie mit Postgres. Andernfalls ist D1 der günstigere Start. Die obige Entscheidungsmatrix ist genau dieselbe, die ich bei Early-Stage-Kunden von TanStack Ship anwende, die fragen "D1 oder Postgres?".