Cloudflare D1とは?従来型RDBMS・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 のインフラ基盤と深く統合された独自のアーキテクチャを持っています。
- User Request
- 世界中のユーザーから最寄りのエッジへ到達
- Cloudflare Workers / Pages Functions
env.DBバインディング経由でコネクションレスにクエリを発行
- 読み取り / 書き込みで振り分けD1 Primary Instance(Durable Object + SQLite)
- Write:書き込み(Primary)はすべてここで直列に処理
- Read:低遅延読み取りは世界各地のエッジにある D1 Read Replica が応答(Primary から複製)
- 自動スナップショット / Time TravelCloudflare R2 Storage
- 永続化・30日間 PITR 復元
D1 を構成する4つの技術的特徴
- SQLite エンジンの採用(インプロセス実行) PostgreSQL や MySQL のようなクライアント・サーバー型ではなく、組み込みデータベースとして世界で最も実績のある SQLite をクエリエンジンとして採用しています。同じプロセス空間(Durable Object 内)で SQL が実行されるため、クエリ単体の実行オーバーヘッドが極小です。
- Durable Objects ベースの単一プライマリ(Single-Writer)モデル
1つの D1 データベースの実体は、Cloudflare のステートフル基盤である Durable Objects の1インスタンスとして稼働します。書き込み処理(
INSERT/UPDATE/DELETE)は常にこの単一プライマリで直列(シングルスレッド)に処理されるため、複雑な分散ロックなしで強い整合性を保ちます。 - コネクションレス(Workers Binding / HTTP API)
TCP ソケットやデータベースコネクションプール(PgBouncer や Cloud SQL Auth Proxy など)は一切不要です。Cloudflare Workers からは環境変数バインディング(
env.DB)を通じて、関数呼び出し感覚で安全にアクセスできます。 - 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 / MySQL | PostgreSQL / MySQL / SQL Server | SQLite(FTS5・JSON関数対応) |
| インフラ形態 | 常時稼働サーバー(VM / コンテナ) | 常時稼働インスタンス(専用VM) | 完全サーバーレス(リクエスト駆動) |
| アイドル時の待機コスト | サーバー代が24時間365日発生 | インスタンス代が24時間365日発生 | 完全 $0(クエリ実行時のみカウント) |
| コネクション管理 | TCP接続(上限管理・プーリング必須) | TCP接続(Proxyやコネクションプール必須) | コネクションレス(Workers Binding) |
| コールドスタート | なし(常時起動) | なし(Aurora Serverless等は数秒発生) | 実質 0ms(数ミリ秒で即時応答) |
| トランザクション方式 | 対話型(BEGIN 〜 COMMIT)・MVCC | 対話型(BEGIN 〜 COMMIT)・MVCC | db.batch() による一括トランザクション |
| 書き込みスケーリング | 垂直スケール(CPU/メモリ増強) | 垂直スケール(インスタンスサイズ変更) | DB分割(テナント単位の水平分割) |
| 読み取りスケーリング | リードレプリカを手動構築 | リードレプリカを追加(追加インスタンス課金) | Global Read Replication(自動エッジ分散) |
| バックアップ / PITR | pg_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 クエリや直列クエリ)を書くと、急激にレスポンスが悪化します。
// ❌ アンチパターン: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つでも失敗すれば、自動的にすべてロールバックされます。
// ✅ ベストプラクティス: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 を操作できます。
// 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コマンドで適用できます。
# ローカル開発用の D1 にマイグレーション適用
npx wrangler d1 migrations apply my-app-db --local
# 本番エッジ環境の D1 にマイグレーション適用
npx wrangler d1 migrations apply my-app-db --remote5.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コマンドで作成できるエッジデータベースの軽快さをぜひ体験してみてください。