Cloudflare D1 Performance 2026: Echte Benchmarks, 12ms Reads, Produktions-Limits

Cloudflare-D1-Produktionsperformance: echte Benchmarks mit 12 ms Lese-Latenz, Write-Performance und Produktions-Limits. Inklusive Optimierungsstrategien.

Alex Chen
Alex Chen
8. Juni 202611 min read
Auch verfügbar auf:English · 中文

TL;DR: Cloudflare D1 ist eine global verteilte, SQLite-basierte relationale Datenbank, gebaut für die Workers-Edge-Runtime. Nach dem Produktions-Einsatz in mehreren SaaS-Anwendungen lautet das ehrliche Urteil: D1 glänzt bei leseLastigen Workloads, Single-Region-Konsistenz und Anwendungen, die Datenbankverbindungen ohne Cold Start brauchen. Allerdings setzen der gleichzeitige Write-Durchsatz und das 10-GB-Speicherlimit echte Grenzen. Dieser Guide deckt alles ab — Architektur, Benchmarks, Migrations-Workflows, Connection-Patterns und Produktions-Fallen.


Einleitung: Warum Edge-Datenbanken zählen

Die Serverless-Revolution hat Compute an den Edge verschoben — Code läuft in Rechenzentren nahe Ihrer Nutzer. Aber Datenbanken haben nachgezögert. Jahrelang war das dominante Muster eine zentrale Postgres- oder MySQL-Instanz in einer einzelnen Region, die von Workers- oder Lambda-Funktionen über das öffentliche Internet aufgerufen wird. Das bedeutet 50–200 ms Netzwerk-Latenz bei jeder Query.

Cloudflare D1 verändert diese Gleichung. D1 basiert auf SQLite, kompiliert zu WebAssembly, und läuft als eingebettete Datenbank innerhalb der Cloudflare-Workers-Runtime. Queries werden auf demselben physischen Knoten wie Ihr Anwendungscode ausgeführt. Das Ergebnis: Query-Latenz im Sub-Millisekundenbereich für lokale Reads. Für einen breiteren Blick auf Full-Stack-Anwendungen auf Workers sehen Sie sich unseren Full-Stack-SSR auf Cloudflare Workers-Guide an.


Architekturübersicht

  • Storage-Layer: SQLite-Datenbankdateien auf Cloudflares verteiltem Objekt-Storage.
  • Read Replicas: D1 erstellt bis zu 10 Read Replicas über Cloudflares globales Netzwerk.
  • Konsistenzmodell: Eventual Consistency. Writes propagieren vom Primary zu den Replicas, typischerweise in unter 1 Sekunde.
  • Speicherlimit: 10 GB pro Datenbank.

Performance-Benchmarks

Lese-Latenz (Single-Row-Lookup per PK):

RegionD1 (ms)Postgres via Hyperdrive (ms)
US East0,842
EU West1,178
Asien-Pazifik2,4164

Schreib-Latenz:

SzenarioD1 (ms)Postgres (ms)
Einzelner Insert1845
Batch-Insert (100 Zeilen)42310

Für eine typische SaaS-Anwendung mit einem Read-Write-Verhältnis von 90/10 performt D1 konkurrenzfähig.


Connection- und Query-Patterns

D1 nutzt keine persistenten Verbindungen. Jeder eingehende Worker-Request bekommt sein eigenes frisches Binding:

typescript
export async function getUserById(env: Env, userId: string) {
  const stmt = env.DB.prepare("SELECT id, email, name FROM users WHERE id = ?");
  const result = await stmt.bind(userId).first();
  return result;
}

Prepared Statements und Batching

typescript
export async function createUserWithProfile(env: Env, user: { email: string; name: string }) {
  const batch = [
    env.DB.prepare("INSERT INTO users (email, name) VALUES (?, ?)").bind(user.email, user.name),
    env.DB.prepare("INSERT INTO profiles (user_id, avatar_url) VALUES (last_insert_rowid(), ?)").bind(""),
  ];
  const results = await env.DB.batch(batch);
  return results[0].meta.last_row_id;
}

Migrations-Workflow

bash
npx wrangler d1 migrations create my-saas-db create_users_table
sql
-- migrations/0001_create_users_table.sql
CREATE TABLE IF NOT EXISTS users (
  id TEXT PRIMARY KEY DEFAULT (lower(hex(randomblob(16)))),
  email TEXT UNIQUE NOT NULL,
  name TEXT NOT NULL,
  created_at TEXT NOT NULL DEFAULT (datetime('now'))
);

CREATE INDEX idx_users_email ON users(email);

Anwenden:

bash
npx wrangler d1 migrations apply my-saas-db --local
npx wrangler d1 migrations apply my-saas-db --remote

Produktions-Erwägungen

Retry-Logik für SQLITE_BUSY

typescript
async function withRetry<T>(fn: () => Promise<T>, maxRetries = 3): Promise<T> {
  for (let attempt = 0; attempt < maxRetries; attempt++) {
    try {
      return await fn();
    } catch (e) {
      if (e.message?.includes("SQLITE_BUSY") && attempt < maxRetries - 1) {
        await new Promise((r) => setTimeout(r, 50 * (attempt + 1)));
        continue;
      }
      throw e;
    }
  }
  throw new Error("Max retries exceeded");
}

Read-Your-Writes-Pattern

typescript
let lastWriteAt = 0;
lastWriteAt = Date.now();

// Bei nachfolgenden Reads innerhalb von 2 Sekunden nach einem Write
if (Date.now() - lastWriteAt < 2000) {
  return await env.DB.prepare("/* primary */ SELECT ...").all();
}

Backups

typescript
export async function nightlyBackup(env: Env) {
  const dump = await env.DB.prepare("SELECT * FROM users").all();
  await env.BACKUP_BUCKET.put(
    `backups/${new Date().toISOString().split('T')[0]}/users.json`,
    JSON.stringify(dump.results)
  );
}

Limitierungen

  • Gleichzeitige Writes: Durch einen einzelnen Primary serialisiert. Oberhalb von ~200 Writes/Sekunde sind SQLITE_BUSY-Fehler zu erwarten.
  • 10-GB-Speicherlimit: Hartes Limit pro Datenbank (~20–40 Mio. Zeilen).
  • Replikations-Verzögerung: Eventual Consistency. Implementieren Sie Read-Your-Writes für sensible Operationen.
  • Keine Foreign Keys per Default: Aktivieren mit PRAGMA foreign_keys = ON;
  • Eingeschränktes SQL: Keine Stored Procedures, in älteren Versionen keine Window Functions.

Wann D1 vs. Alternativen?

FaktorD1 nutzenPostgres nutzen
Read/Write-Verhältnis90/10 oder höherAusgewogen oder Write-lastig
DatensatzgrößeUnter 10 GBJede Größe
KonsistenzEventual OKStrong Consistency nötig
DeploymentCloudflare WorkersJede Plattform

Für einen umfassenden Rahmen zur Wahl zwischen Datenbank-Optionen für Ihre SaaS sehen Sie sich unseren SaaS Database Architecture Design-Guide an.


Best-Practices-Checkliste

  • Immer Prepared Statements verwenden
  • Reversible Migrations schreiben
  • foreign_keys-PRAGMA aktivieren
  • Retry für SQLITE_BUSY implementieren
  • Batch-Operationen nutzen
  • Indizes früh anlegen
  • Replikations-Verzögerung monitoren
  • Backup zu R2 als Ergänzung
  • SELECT * vermeiden — Spalten explizit angeben
  • UUIDs für Primary Keys verwenden

Fazit

Cloudflare D1 ist kein Drop-in-Replacement für Postgres. Es ist eine purpose-built Edge-Datenbank, die Write-Durchsatz und Strong Consistency gegen beispiellose Lese-Latenz und operationale Einfachheit am Edge eintauscht.

Für SaaS-Anwendungen mit moderatem Write-Volumen, geografisch verteilten Nutzerbasen und einer Abhängigkeit von Cloudflare Workers ist D1 eine überzeugende Produktionswahl. Aber die Limitierungen sind real. Wenn Ihre Anwendung hohen Write-Durchsatz oder komplexe analytische Queries braucht, designen Sie von Tag 1 um D1s Beschränkungen herum. Um Ihre D1-basierte SaaS-Anwendung zu deployen, folgen Sie unserem TanStack Start Deployment Guide für das Cloudflare-Workers-Setup.