Skip to content
返回文章列表
Infrastructure15分

Cloudflare Workers と Durable Objects 徹底解剖: グローバル・ステートマシンの設計原理

Cloudflare Workers & Durable Objects Deep Dive: Designing Global State Machines

村田 聡Principal Edge Architect
2026-04-2115分
CloudflareWorkersDurable ObjectsWASMRustTypeScriptEdge Computing

本文以日语发表。中文摘要如下:

Cloudflare Workers & Durable Objects Deep Dive: Designing Global State MachinesDurable Objects の単一スレッド・トランザクションモデル、Workers KV / Hyperdrive / D1 の使い分け、Workers AI の推論ルーティング、Rust + WASM バインディングによるホットパス最適化まで、2026年時点の実装ノウハウを体系化する。

Workers プラットフォームを俯瞰する

Cloudflare Workers は V8 Isolate を基盤とした FaaS で、2026年4月時点で330都市以上の PoP に同一コードが即時デプロイされる。コールドスタートは実質ゼロに近い(多くのリクエストで 5ms 未満)一方、AWS Lambda のようなコンテナ起動ではなく Isolate を使う制約から、Node.js ネイティブモジュールや長時間ブロッキング I/O は本質的に合わない。2025年後半に GA した nodejs_compat_v2 により fs / crypto / stream の互換が大幅に改善したが、依然として「Isolate の作法」を理解せずに書くと、サブリクエスト上限(1000)や CPU time 制限(有料プランで 5 分)に衝突する。

Workers が真に価値を発揮するのは、ステートフルなロジックを Durable Objects と組み合わせた瞬間である。Durable Object(以下 DO)は「グローバルに一意な ID を持つ、単一スレッド・強整合性のアクター」であり、リクエストは同一 DO に対して必ずシリアライズされる。このモデルは「エッジにおける mutex の代替」として設計されており、従来 Redis や Postgres の advisory lock で実装していた「ユーザー単位のレート制限」「会議室単位のシグナリング」「取引 ID 単位の在庫引当」を、RTT を挟まずローカルに完結させられる。

Durable Objects のトランザクションモデル

DO の永続ストアは内部的に SQLite ベースの storage API を提供する。2025年に SQLite-backed DO が全プラン解放されて以降、1 DO あたり最大 10GB まで関係データを格納でき、transaction() コールバック内で複数の put / delete を原子的に実行できる。重要なのは DO が「入力ゲート」と「出力ゲート」を内包している点である。入力ゲートはリクエスト処理中の storage 書き込み待ちで新しいリクエストをブロックし、出力ゲートは storage 書き込みが永続化されるまで fetch レスポンスを保留する。この二重ゲートにより、アプリケーションコードは async / await を自由に書いても整合性が壊れない。

```typescript export class InventoryDO { state: DurableObjectState; constructor(state: DurableObjectState) { this.state = state; } async fetch(req: Request) { const { sku, qty } = await req.json<{ sku: string; qty: number }>(); return await this.state.storage.transaction(async (tx) => { const current = (await tx.get<number>(sku)) ?? 0; if (current < qty) return new Response("oos", { status: 409 }); await tx.put(sku, current - qty); return new Response(JSON.stringify({ remain: current - qty })); }); } } ```

DO をアクター的に使う際の誤用として多いのが「1 DO で全テナントを処理する」設計である。DO はホットスポットになると PoP が固定され、地理的に離れたユーザーに高 RTT を強いる。正解は idFromName() で「テナント ID + リソース ID」を連結してシャーディングし、書き込みが地理的局所性を持つように配置することだ。読み込みは replica DO(2025年 GA)で非同期レプリカから O(1) で返せる。

Workers KV, Hyperdrive, D1 の使い分け

三つのデータ層は目的が明確に分かれている。Workers KV は結果整合の読み取り最適化ストアで、60秒以内の伝播を許容できる設定値・メタデータに向く。PUT の伝播遅延は数秒から60秒、読み取りは PoP ローカルキャッシュから 1ms で返る。Hyperdrive は外部 Postgres / MySQL への接続プーラで、オリジンへの TCP 接続を再利用しつつクエリ結果を PoP でキャッシュする。既存 RDB 資産を持つ組織がエッジ移行する際の第一歩として最も現実的である。D1 は Cloudflare 自前の SQLite ベース RDB で、2025年に read replica が GA し、書き込みはプライマリ、読み取りは最寄り replica という PostgreSQL 風のトポロジを取れる。

選定の基準は「書き込み頻度」と「整合性要件」で分解する。秒間 1000 書き込み以上でテナント単位に分離可能なら DO、グローバルな少数 write + 地理分散 read なら D1、外部 DB が既にあるなら Hyperdrive、TTL ベースの設定配布なら KV というのが実務の定石だ。R2(S3 互換オブジェクトストレージ)はこれらと直交し、エグレス無料という特性を活かして動画配信・バックアップ・データレイクに使う。

Workers AI と推論ルーティング

Workers AI は 2024年 GA 以降、Llama 3.3 70B、Mistral Large 2、GPT-OSS-120B、Qwen 3 系など主要 OSS モデルを従量課金で呼び出せる。2026年現在は BYOK で OpenAI / Anthropic / Google を同一 API(AI Gateway)経由でルーティングでき、レスポンスキャッシュ・再試行・レート制限を Workers 側で統一管理できる点が優位性となっている。AI Gateway のログは Analytics Engine に流れるため、プロンプト毎のトークンコストを SQL でクエリできる。

レイテンシ最適化の定石は「小さい判定は Workers AI のローカル推論、複雑な推論は外部 LLM」というハイブリッドである。例えば Bot 判定・NSFW 分類・多言語検出を Workers AI の Llama Guard / Llama-3 8B で済ませ、結果が「不確実」な場合のみ Claude や GPT に昇格させる二段階ルーティングで、コストを 70% 削減した事例を弊社でも複数確認している。

Rust + WASM バインディングによるホットパス最適化

TypeScript で 5ms、Rust + WASM で 0.8ms。この差が秒間 10 万リクエストで効いてくると、CPU time 予算に直結する。workers-rs(Rust crate)は #[event(fetch)] マクロで Workers ランタイムにコンパイルでき、wasm-bindgen 経由で JS API(fetch / crypto / R2)にアクセスできる。JSON パースが重い API ゲートウェイや、HMAC 検証・JWT 検証・画像リサイズを Rust で書き換えるとコスト削減効果が大きい。

```rust use worker::*; #[event(fetch)] async fn main(req: Request, env: Env, _ctx: Context) -> Result<Response> { let body: serde_json::Value = req.json().await?; let signature = req.headers().get("x-signature")?.unwrap_or_default(); if !verify_hmac(&body, &signature, &env.secret("HMAC_KEY")?.to_string()) { return Response::error("invalid signature", 401); } Response::ok("ok") } ```

注意点として、WASM モジュールサイズは 10MB までに抑えるべきで、wasm-opt -Oz と wee_alloc の組合せで実効サイズを半減できる。起動コストは Isolate 再利用によりほぼ無視できるが、初回コンパイルは 20–50ms かかるため、トラフィックが極端に低い PoP では TypeScript の方が速い逆転現象も起きる。ベンチマークは本番 PoP で取るのが必須である。

グローバル・ステートマシンの構築パターン

WebSocket Hibernation + Durable Objects の組合せは、リアルタイム協調編集・ライブ配信のシグナリング・IoT デバイスオーケストレーションの定番となった。Hibernation API により、WebSocket 接続は開いたままメモリを解放でき、DO の請求は「アクティブ時間」のみになる。100万接続を維持しても月額数千ドルに収まるコスト構造が、Ably や Pusher 的サービスを自前で作り直す動機を生んでいる。

設計上の勘所は、DO を「ステートマシンの単一ノード」として扱うことだ。状態遷移は storage.transaction 内で state version を CAS 更新し、外部イベントは Queues 経由で発火する。失敗時の補償トランザクションは alarm() API で遅延実行できる。これで「エッジで始まり、エッジで終わる」サーガパターンを低レイテンシで組める。オリジンに戻らないアーキテクチャが、2026年の分散システム設計の主戦場である。

技術的な課題を一緒に解決しませんか?

KGA IT Solutionsは、AI・クラウド・DevOpsの専門チームがお客様の課題に最適なソリューションを提供します。

お問い合わせ