Cloudflare D1 vs Postgres: Limits, Preise, Entscheidungsmatrix

Cloudflare D1 vs Postgres getestet in 4 Produktions-SaaS über 18 Monate: Echte Limits, Preise und eine Entscheidungsmatrix. TanStack Ship liefert D1.

Huifer
Huifer
9. Mai 202612 min read
Auch verfügbar auf:English · 中文

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 GB benö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-StrukturEmpfohlene EngineWarum
Leseintensive SaaS, < 10M Zeilen, Workers-nativD1Sub-Millisekunden-Lesezugriffe, Zero Pool, eine einzige Abrechnungsposition
Schreibintensive SaaS, < 50 Writes/SekundeD1Ein einzelner Writer reicht aus; > 50 Writes/Sekunde und Sie spüren den Lock
Schema mit JSONB oder GIN-indizierten ObjektenPostgresSQLite JSON1 ist das falsche Tool für tiefe Objekt-Queries
Volltextsuche bei User-ContentPostgrestsvector + pg_trgm schlagen FTS5 bei Setup-Kosten und Ranking-Qualität
Echtzeit-Change-Feed zu ClientsPostgresLISTEN/NOTIFY ist ein Query; auf D1 müssen Sie es manuell verdrahten
>10 GB Datenbank oder B2C-MedienkatalogPostgresJenseits der 10 GB D1-Grenze; Neons kleinster Plan bewältigt das
Kaltstart-empfindliche User-Facing APID1Sub-Millisekunden-Lesezugriffe schlagen 1,2 s Neon-Kaltstart bei gleichem Query
Regionenübergreifender Fan-Out, geringe SchreibrateD1Kostenlose 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

sql
-- 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

sql
-- 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/NOTIFY oder einer der 200+ Postgres-Extensions profitiert, machen sich die Migrationskosten durch das saubere Schema bezahlt.
  • Postgres gewinnt bei >10 GB oder 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?".