☁️ Web・クラウド構築

Cloudflare D1とは?従来型RDBMS・Cloud SQLとの徹底比較からコスト・パフォーマンス・設計の勘所まで解説

#Cloudflare D1#Cloudflare Workers#SQLite#Cloud SQL#データベース設計#コスト削減

Cloudflare Pages や Workers、オブジェクトストレージの Cloudflare R2 を使って Web アプリケーションを構築する際、「リレーショナルデータベース(RDB)はどこに置くべきか?」という問題に必ず直面します。

これまでエッジサーバーレス環境(Cloudflare Workers 等)から Google Cloud SQL や AWS RDS のような従来型のクラウド RDBMS に接続しようとすると、TCP コネクション枯渇問題やリージョン間の通信レイテンシ、そして何より「アクセスがゼロでも毎月数千円〜数万円が飛び続けるインスタンス維持費」が大きな壁となっていました。

この課題を Cloudflare 独自のアプローチで解決したのが、SQLite ベースのサーバーレスリレーショナルデータベース 「Cloudflare D1」 です。

本記事では、Cloudflare D1 の内部アーキテクチャや性質を紐解きながら、従来型 RDBMS(PostgreSQL / MySQL)やマネージド DB(Cloud SQL / RDS)との構造的な違い、コスト、パフォーマンス特性、そして実務で採用する際のメリット・制約までを多角的に解説します。


1. Cloudflare D1 とは?アーキテクチャの本質を理解する

一言で表すと、Cloudflare D1 は 「Cloudflare のエッジネットワーク(Durable Objects)上で稼働する、サーバーレスな分散 SQLite データベース」 です。

単なる「クラウド上の SQLite ファイル」ではなく、Cloudflare のインフラ基盤と深く統合された独自のアーキテクチャを持っています。

Cloudflare D1 のアーキテクチャ(Cloudflare Edge Network 内で完結)
  1. User Request
    • 世界中のユーザーから最寄りのエッジへ到達
  2. Cloudflare Workers / Pages Functions
    • env.DB バインディング経由でコネクションレスにクエリを発行
  3. 読み取り / 書き込みで振り分け
    D1 Primary Instance(Durable Object + SQLite)
    • Write:書き込み(Primary)はすべてここで直列に処理
    • Read:低遅延読み取りは世界各地のエッジにある D1 Read Replica が応答(Primary から複製)
  4. 自動スナップショット / Time Travel
    Cloudflare R2 Storage
    • 永続化・30日間 PITR 復元

D1 を構成する4つの技術的特徴

  1. SQLite エンジンの採用(インプロセス実行) PostgreSQL や MySQL のようなクライアント・サーバー型ではなく、組み込みデータベースとして世界で最も実績のある SQLite をクエリエンジンとして採用しています。同じプロセス空間(Durable Object 内)で SQL が実行されるため、クエリ単体の実行オーバーヘッドが極小です。
  2. Durable Objects ベースの単一プライマリ(Single-Writer)モデル 1つの D1 データベースの実体は、Cloudflare のステートフル基盤である Durable Objects の1インスタンスとして稼働します。書き込み処理(INSERT / UPDATE / DELETE)は常にこの単一プライマリで直列(シングルスレッド)に処理されるため、複雑な分散ロックなしで強い整合性を保ちます。
  3. コネクションレス(Workers Binding / HTTP API) TCP ソケットやデータベースコネクションプール(PgBouncer や Cloud SQL Auth Proxy など)は一切不要です。Cloudflare Workers からは環境変数バインディング(env.DB)を通じて、関数呼び出し感覚で安全にアクセスできます。
  4. R2 バックアップと「Time Travel(タイムトラベル)」標準搭載 データは自動的に Cloudflare R2 上へ継続的にバックアップされており、設定不要で過去30日間の任意の分単位の時点へデータベースを巻き戻せる(Point-in-Time Recovery)機能を備えています。

2. 従来型 RDBMS・Cloud SQL / AWS RDS との徹底比較

オンプレミスや VPS 上で運用する従来型 RDBMS(PostgreSQL / MySQL)、クラウドマネージド型の代表格である Google Cloud SQL(や AWS RDS)、そして Cloudflare D1 を主要項目で比較してみましょう。

比較観点従来型 RDBMS (自前構築 PostgreSQL / MySQL)クラウドマネージド RDB (Google Cloud SQL / AWS RDS)Cloudflare D1 (Edge Serverless SQLite)
SQL ダイアレクトPostgreSQL / MySQLPostgreSQL / MySQL / SQL ServerSQLite(FTS5・JSON関数対応)
インフラ形態常時稼働サーバー(VM / コンテナ)常時稼働インスタンス(専用VM)完全サーバーレス(リクエスト駆動)
アイドル時の待機コストサーバー代が24時間365日発生インスタンス代が24時間365日発生完全 $0(クエリ実行時のみカウント)
コネクション管理TCP接続(上限管理・プーリング必須)TCP接続(Proxyやコネクションプール必須)コネクションレス(Workers Binding)
コールドスタートなし(常時起動)なし(Aurora Serverless等は数秒発生)実質 0ms(数ミリ秒で即時応答)
トランザクション方式対話型(BEGIN 〜 COMMIT)・MVCC対話型(BEGIN 〜 COMMIT)・MVCCdb.batch() による一括トランザクション
書き込みスケーリング垂直スケール(CPU/メモリ増強)垂直スケール(インスタンスサイズ変更)DB分割(テナント単位の水平分割)
読み取りスケーリングリードレプリカを手動構築リードレプリカを追加(追加インスタンス課金)Global Read Replication(自動エッジ分散)
バックアップ / PITRpg_dump / WALアーカイブ等を自前設計自動バックアップ・PITR(ストレージ課金)Time Travel 標準内蔵(追加設定・課金なし)
1DBあたりの容量上限ディスク容量次第(数TB〜)最大 64TB〜最大 10GB / DB(無制限にDB作成可能)

構造的な違い①:コネクションプール問題の消滅

Cloud SQL や RDS を Cloudflare Workers や AWS Lambda などのサーバーレス関数から利用する場合、最大のボトルネックになるのが 「TCP コネクションの確立コストと接続数上限」 です。 アクセスが急増して数百個のサーバーレス関数が同時に立ち上がると、RDBMS 側の max_connections が一瞬で枯渇し、接続エラーを引き起こします。これを防ぐには PgBouncer や RDS Proxy、Hyperdrive などのミドルウェアを挟む必要がありました。

一方、Cloudflare D1 は最初からサーバーレス環境専用に設計されているため、Workers からは env.DB.prepare(...) を呼ぶだけで、Cloudflare 内部の高速 RPC 経由でクエリがルーティングされます。接続上限や TLS ハンドシェイクのオーバーヘッドを気にする必要がありません。

構造的な違い②:トランザクションの考え方(MVCC vs バッチ実行)

PostgreSQL や MySQL(InnoDB)は MVCC(多版型同時実行制御) と行レベルロックを備えており、ネットワーク越しに BEGIN を発行してからアプリケーション側で条件分岐を行い、最後に COMMIT / ROLLBACK する「対話型トランザクション(Interactive Transactions)」が得意です。

それに対し、SQLite ベースの D1 では、1つのデータベースに対する書き込みは単一スレッドで順番(直列)に高速実行されます。 もしネットワーク越しのクライアントが BEGIN でロックを握ったまま通信遅延を起こすと、データベース全体の書き込みが詰まってしまいます。


3. コスト面の比較:なぜ D1 は「個人開発〜中規模 SaaS」で破壊的に安いのか?

データベース選定において、Cloud SQL や RDS と Cloudflare D1 の差が最も顕著に表れるのが コスト構造 です。

Cloud SQL / AWS RDS のコスト構造(時間課金+容量+通信費)

Google Cloud SQL や AWS RDS は「仮想マシン(インスタンス)を専有して常時起動させておく」モデルです。

  • 検証用の最小構成(共有コア db-f1-micro 等) であっても月額 $10〜$15(約1,500円〜2,300円)程度かかります。
  • 本番運用に耐える構成(高可用性 HA 構成+専用 vCPU+自動バックアップ+固定パブリック IP) にすると、アクセスが1件もなくても月額 $70〜$200(約1万〜3万円以上) が固定費として発生します。
  • さらに、クラウド外(Cloudflare Workers 等)へデータを返す際には エグレス通信料金(データ転送料) が加算されます。

Cloudflare D1 のコスト構造(完全従量課金+エグレス無料)

Cloudflare D1 には「コンピューティング時間(CPU稼働時間)に対する課金」も「データ転送料(エグレス料金)」も存在しません。課金対象はシンプルに以下の3つだけです。

項目無料枠(Workers Free / Paid 共通のベース)Workers Paid($5/月)プランの無料枠・超過単価
読み取り行数 (Rows Read)1日あたり 500万行 まで無料月間 250億行 まで込み / 超過分 $0.001 / 100万行
書き込み行数 (Rows Written)1日あたり 10万行 まで無料月間 5,000万行 まで込み / 超過分 $1.00 / 100万行
ストレージ容量合計 5GB まで無料5GB まで込み / 超過分 $0.75 / GB・月
エグレス通信費(データ転送)完全無料 ($0)完全無料 ($0)

コスト面での重要なポイントと1つの罠

  • アイドルコストが完全ゼロ:夜間や休日にアクセスがない社内ツール、個人開発の Web サービス、マイクロサービスを何十個立ち上げても、クエリが走らなければ維持費は $0 です。

4. パフォーマンスの性質:速さの秘密とレイテンシの勘所

「D1(SQLite)はPostgreSQLより速いのか?遅いのか?」という疑問に対しては、「クエリエンジン自体の実行速度」と「ネットワーク往復(RTT)」の2つを分けて考える必要があります。

4.1 クエリ実行速度:インプロセス SQLite の圧倒的な瞬発力

D1 のプライマリインスタンス(Durable Object)の内部では、SQLite のデータがローカルディスク(NVMe SSD)およびメモリキャッシュ上に展開されています。 そのため、単純な主キー検索やインデックスが効いた SELECT クエリであれば、データベース内部での処理時間(SQL Duration)は 0.1ms〜2ms 程度という驚異的な速さで完了します。

4.2 ネットワーク往復(RTT)の壁と「チャット型クエリ」の罠

Cloudflare Workers はユーザーに最も近いエッジ(例:東京)で起動しますが、もし D1 のプライマリデータベースが北米リージョンに作成されていた場合、1回のクエリにつき日米間の通信往復(約 100ms〜150ms)が発生します。 この状態で、以下のようにループ内で何度も await するコード(N+1 クエリや直列クエリ)を書くと、急激にレスポンスが悪化します。

TypeScript
// ❌ アンチパターン:3回のネットワーク往復(3 RTT)が発生する
const user = await env.DB.prepare('SELECT * FROM users WHERE id = ?').bind(userId).first();
const posts = await env.DB.prepare('SELECT * FROM posts WHERE user_id = ?').bind(userId).all();
await env.DB.prepare('UPDATE users SET last_seen_at = CURRENT_TIMESTAMP WHERE id = ?').bind(userId).run();

4.3 D1 のパフォーマンスを極限まで引き出す3つの鉄則

① db.batch() で1回のネットワーク往復(1 RTT)にまとめる

複数のクエリを実行する場合や、書き込みトランザクションを行う場合は、必ず env.DB.batch() を使用します。これにより、何十個のクエリであっても 1回のネットワーク往復(1 RTT) で D1 プライマリへ送信され、内部で一括トランザクション実行されます。もし途中で1つでも失敗すれば、自動的にすべてロールバックされます。

TypeScript
// ✅ ベストプラクティス:1回の通信(1 RTT)で全クエリを一括実行&トランザクション保証
const [userResult, postsResult] = await env.DB.batch([
  env.DB.prepare('SELECT * FROM users WHERE id = ?').bind(userId),
  env.DB.prepare('SELECT * FROM posts WHERE user_id = ? ORDER BY created_at DESC LIMIT 10').bind(userId),
  env.DB.prepare('UPDATE users SET last_seen_at = CURRENT_TIMESTAMP WHERE id = ?').bind(userId),
]);

② 作成時の Location Hint 指定と「Global Read Replication(リードレプリカ)」の活用

日本のユーザーがメインのサービスであれば、D1 作成時に --location=apac(アジア太平洋)を指定するか、プライマリ作成を日本国内から実行して物理ロケーションを近くに配置します。

さらに、グローバルに展開するサービスや読み取り比率が高いサービスでは、D1 の Read Replication(Sessions API) を有効化します。

  • Sessions API(env.DB.withSession()) を使うと、読み取りクエリ(SELECT)はユーザーの最寄りのエッジにあるリードレプリカで高速に処理され、書き込み(INSERT/UPDATE)が発生した後は、セッションブックマークによって「自分が書き込んだ直後のデータを確実に読める(Read-your-own-writes 整合性)」を保証しながら世界中どこからでも低遅延で応答できます。
  • また、1リクエスト内で何度も DB とやり取りする重いバックエンド処理では、Workers の Smart Placement を有効にすることで、Worker 自体をユーザーの近くではなく「D1 プライマリがあるデータセンターのすぐ隣」で実行させ、DB 間の通信遅延を 1ms 未満に抑えることも可能です。

③ スループット上限の理解(単一スレッドの限界)

D1 のプライマリは単一スレッドで動作するため、1つのクエリに 1ms かかるとすると、理論上の書き込み上限は 1データベースあたり秒間約 1,000 クエリ(QPS)前後 になります。 通常の Web サービスや SaaS であれば十分すぎる性能ですが、秒間数万件の IoT センサーデータ書き込みや超大規模ゲームの全体ランキング更新などを1つの D1 データベースに集中させると詰まります。


5. その他の重要な観点:開発体験(DX)・エコシステム・機能性

コストやパフォーマンス以外にも、Cloudflare D1 には従来の RDBMS とは異なるユニークな強みと設計パターンがあります。

5.1 「1ユーザー(1テナント)= 1データベース」という新発想

Cloud SQL や RDS では、インスタンス1台あたりのコストが高いため、全顧客のデータを1つの巨大なデータベースに入れ、tenant_id カラムで分離する設計(Shared-Database Multi-Tenancy)が一般的でした。

一方、D1 は Workers Paid プランであれば何千・何万個でもデータベースを軽量に作成でき、維持費もゼロです。また、1データベースあたり最大 10GB という上限があります。 そのため、B2B SaaS やプロジェクト管理ツールなどでは、「顧客企業(テナント)やワークスペースごとに専用の D1 データベースを丸ごと1つ割り当てる(Database-per-Tenant)」 というアーキテクチャが現実的に採用できます。

  • 顧客ごとのデータが物理的に完全分離されるため、万が一の SQL バグによる他社データの漏洩リスクがゼロになる。
  • 特定の顧客が大量のクエリを発行しても、他の顧客のデータベースのパフォーマンスに一切影響しない(Noisy Neighbor 問題の解消)。
  • 特定の顧客のデータだけを Time Travel で過去時点にリストアできる。

5.2 Drizzle ORM との抜群の親和性と型安全開発

TypeScript で Cloudflare Workers + D1 を扱う場合、軽量で SQL ライクな Drizzle ORM(または Kysely)と組み合わせるのが現在のデファクトスタンダードです。TanStack Start や Astro のサーバー関数からも、以下のように100%型安全に D1 を操作できます。

TypeScript
// src/db/schema.ts
import { sqliteTable, text, integer, index } from 'drizzle-orm/sqlite-core';

export const articles = sqliteTable(
  'articles',
  {
    id: integer('id').primaryKey({ autoIncrement: true }),
    slug: text('slug').notNull().unique(),
    title: text('title').notNull(),
    views: integer('views').notNull().default(0),
    publishedAt: integer('published_at', { mode: 'timestamp' }).notNull(),
  },
  (table) => [
    // Rows Read を最小化するための複合インデックス定義
    index('idx_articles_published_at').on(table.publishedAt),
  ]
);

Wrangler CLI を使えば、ローカル環境(.wrangler/state 内のローカル SQLite)と本番エッジ環境の両方に対して、同じマイグレーションファイルを1コマンドで適用できます。

Terminal
# ローカル開発用の D1 にマイグレーション適用
npx wrangler d1 migrations apply my-app-db --local

# 本番エッジ環境の D1 にマイグレーション適用
npx wrangler d1 migrations apply my-app-db --remote

5.3 全文検索(FTS5)と JSON クエリの標準サポート

D1 の SQLite エンジンには拡張モジュールの FTS5(Full-Text Search 5) や json_extract() / -> 演算子が組み込まれています。 そのため、別途 Elasticsearch や Algolia などの外部検索エンジンを契約しなくても、ブログ記事の検索や商品カタログの高速な全文検索、柔軟なメタデータ検索を D1 単体で完結させることができます。


6. 結論:Cloudflare D1 を選ぶべきケース vs Cloud SQL 等を選ぶべきケース

ここまでの比較を踏まえ、プロジェクトの性質に応じたデータベース選定基準を整理します。

✅ Cloudflare D1 が最高に輝くユースケース

  • Cloudflare Workers / Pages をメインのコンピューティング基盤として採用している Web アプリ・API
  • 読み取り比率が高いサービス(ブログ・CMS・ECの商品カタログ・認証セッション管理・設定ストアなど)
  • 個人開発・スタートアップ・社内ツールなど、初期固定費やアイドル時のインフラ維持費を限りなく $0 に抑えたいプロジェクト
  • マルチテナント SaaS で、テナント(顧客・組織)ごとにデータベースを物理分割したいケース
  • コネクションプールや VPC ネットワーク設計、DB パッチ当てなどのインフラ運用コストをゼロにしたい少人数チーム

⚠️ Cloud SQL / AWS RDS(PostgreSQL / MySQL)を選ぶべきユースケース

  • 1つの単一データベースで数十GB〜数TBを超える巨大データを扱う必要があり、テナント分割も難しい場合(D1 は 1DB あたり 10GB 上限)
  • 秒間数千〜数万件の激しい同時書き込み(Write-Heavy)が単一テーブルに集中し、厳密な行ロック(SELECT ... FOR UPDATE)や対話型トランザクションが不可欠な基幹・金融システム
  • PostgreSQL 固有の高度な拡張機能(PostGIS による複雑な地理空間演算、pgvector による大規模ベクトル検索、ストアドプロシージャ、複雑なマテリアライズドビュー等)に強く依存している場合(※なお、Cloudflare 環境でベクトル検索を行いたい場合は Cloudflare Vectorize と D1 を組み合わせる構成が推奨されます)
  • BI ツール等から直接重たい OLAP(集計・分析)クエリを長時間走らせるデータウェアハウス用途

まとめ

Cloudflare D1 は、「すべての面で PostgreSQL や Cloud SQL を置き換える万能の銀の弾丸」ではありません。1データベースあたり 10GB というサイズ上限や、SQLite ベースの単一プライマリモデルという明確な割り切りがあります。

しかし、その割り切りと引き換えに手に入る以下の4つは、現代のサーバーレス Web 開発において他に代えがたい強力な武器になります。

まずは手元の個人開発プロジェクトやマイクロサービス、あるいは Cloudflare Pages / Workers 上の API バックエンドから、wrangler d1 create の1コマンドで作成できるエッジデータベースの軽快さをぜひ体験してみてください。


📚 関連する技術記事

Web・クラウド構築の記事一覧 →

HTML-in-Canvas 解説:canvas に本物の HTML を描く新 API と、ブラウン管風レトロコンソールのデモ

<canvas> の中に DOM を描画できる HTML-in-Canvas(drawElementImage / texElementSubImage2D / paint イベント)の仕組みと Chrome での提供状況を解説し、WebGL シェーダーで走査線・湾曲・残光を再現したブラウン管風コンソールのデモを実装・検証します。