数百万のデータベースをどう回してる?D1 コントロールプレーンの裏側、のぞいちゃった!
こんにちは、しぃちゃんだよ!D1 がどうやって数百万のデータベースを支えているのか、設計の中身が公開されたよ!
Cloudflare Blogなにが発表されたの?
Cloudflare の Blog で、D1 のコントロールプレーンのアーキテクチャが解説されたの。D1 は SQLite ベースのサーバーレスデータベースで、データベース 1 つにつき SQLite の Durable Object が 1 つ付くよ。この記事は、数百万のデータベースを管理しながら、クエリ処理はエッジに置き続ける設計の話だよ。
なぜ重要なの?
2026 年 10 月 8 日時点で、削除されていないデータベースは 1 年で 15 倍、2 年で 65 倍に増えているの。1 日に 1 回以上クエリを実行した「アクティブ」なデータベースも 1 年で 18 倍。数百万が作られ、常時数十万がアクティブという規模だよ。
これで何が変わるの?
この記事は、Developer Platform の上で大規模なシステムを組むときの指針を示してくれているよ。ホットパスに中央集権的なコンポーネントを置かない考え方は、D1 以外にも応用できるね。
深く潜ってみよう
操作は 3 つに分けて考えているよ。
- データプレーン: クエリ要求。最速で、常にエッジで動かす
- コントロールプレーン: HTTP API や非クエリ要求の内部フロー。中央の単一リージョンのコンポーネントに依存してよい
- バックグラウンドの非同期プレーン: 分析と課金。結果整合でよく、どこで動いてもよい
主なコンポーネントはこれだよ。
- Edge API Worker: ダッシュボード、Wrangler、CLI の API を受け、認証・認可・レート制限・検証・権限チェックを行う
- Eyeball Worker: D1 の Durable Object へのリクエストを中継し、可観測性、リトライ、エラー処理をまとめる
- Durable Objects: データベースごとに 1 つ。メタデータと状態を持ち、SQL を実行する
- Postgres(Core): データベースのメタデータの正本。Hyperdrive 経由でアクセス
- Workers KV: データベース ID から Durable Object への対応などのルーティング情報
- Queues: Durable Object から Postgres への書き込みを平準化
- ClickHouse: 分析、ストレージの履歴スナップショット、課金に使う行使用量イベント
- Quicksilver: 制限の適用フラグに使う、グローバルに複製された内部 KV ストア
設計原則は 7 つ挙がっているよ。
- すべてのプロセスを失敗と冪等性を前提に設計する
- データプレーン、特にクエリのホットパスに中央集権的な単一リージョンのコンポーネントを置かない
- 重要なルーティング情報には Workers KV を使い、キャッシュミスが中央 DB に届きにくくする
- Hyperdrive で接続プールとキャッシュを効かせ、リードレプリカを優先する
- 集計は事前計算して、リクエスト処理中にスキャンしない
- 強い一貫性が要らない部分は結果整合とキューでつなぐ
- 現実的なワークロードで負荷試験し、見つかったボトルネックから直す
データベース作成のフローはこうだよ。
- アカウントのデータベース数を無料枠やアカウント上限と照合する
- UUID と
newUniqueId()で新しい Durable Object ID を作って初期化する - メタデータと DO のマッピングを Postgres に書く。この書き込みが「作成のチェックポイント」で、最後の応答がユーザーに届かなくても作成済みとみなす
- マッピングを Workers KV にベストエフォートで書く
リトライのたびに新しい ID を使うのは、同じ UUID に別の DO ID を割り当てると複数の DO が同じデータベースを名乗ってしまうからだよ。DO を Postgres への書き込みより先に初期化するのは、未初期化のオブジェクトにクエリが届かないようにするためなの。
それぞれの Durable Object は 30 秒ごと(データベースごとのジッター付き)にコントロールプレーンへハートビートを送るよ。孤立した DO は自分が削除済みだと気づけるし、Workers KV の状態の修復にも使われるの。
クエリのホットパスでは、Edge API Worker が Workers KV でマッピングを引き、まれなミスのときだけ Hyperdrive 経由の Postgres レプリカに行くよ。その後 Eyeball Worker を経由して Durable Object へ。D1 バインディングを持つユーザー Worker は、この検索を飛ばして直接 Eyeball Worker に行けるの。
ストレージ上限は Free が 1 アカウント 5 GB、Workers Paid が 1 TB(依頼で引き上げ可能)。使用量の更新は Queue 経由で集計され、スケジュールジョブが 1 秒ごとに差分をアカウント単位に集計するよ。上限を超えたら、DO がサイズを増やす書き込みを止めるの。Free の 1 日の行数上限は、ClickHouse の使用量イベントを元に Limiter が超過アカウントを探し、メール通知と Quicksilver のフラグで DO がエッジでクエリを拒否する仕組みだよ。
まとめ
- クエリはエッジ、管理は中央、集計は非同期と役割を分けている
- Postgres、KV、ClickHouse、Quicksilver を用途ごとに使い分けている
- ホットパスから単一リージョンの部品を外し、ハートビートで自己修復する
- 上限の適用は事前集計とフラグで、スキャンなしに行う
大規模なマルチテナント設計やサーバーレス基盤の作り方に興味がある人に刺さるよ!