Dynamic WorkersのDurable Objects:各AI生成アプリに専用データベースを与える
数週間前、Workersプラットフォームの新機能である Dynamic Workers を発表しました。これは安全なサンドボックスにWorkerコードをオンザフライで読み込める機能です。Dynamic Worker Loader API は、本来 Workers が依拠してきた基本的なコンピュート分離プリミティブ、すなわちコンテナではなく「isolates」への直接アクセスを提供します。isolates はコンテナよりはるかに軽量で、100x 速く、メモリは 1/10 で起動できます。効率が高いため、使い捨てのように扱えます:数行のコードを実行するために起動し、実行後に破棄する──secure な eval() のようなものです。
Dynamic Workers は多用途です。最初の発表では、AIエージェントが生成したコードをツール呼び出しの代替として実行する方法に焦点を当てました。このユースケースでは、AIエージェントがユーザーの要求に応じて数行のコードを書いて実行し、それは一度限りの単発処理で実行後に廃棄されます。
しかし、もし AI により永続的なコードを生成してほしい場合はどうでしょうか?ユーザーが操作できるカスタム UI を持つ小さなアプリケーションを AI に構築させたい場合は?そのアプリに長期の状態を持たせたい場合は?もちろん、依然として安全なサンドボックスで動かしたいでしょう。
一つのアプローチは Dynamic Workers を使い、Worker にストレージへの RPC API を提供することです。bindings を使えば、Dynamic Worker に Cloudflare D1 や Hyperdrive 経由でアクセスする Postgres など、リモート SQL データベースを指す API を与えられます。しかし、Workers にはこのユースケースにぴったり合う、非常に高速な独自のストレージがあります:Durable Objects です。
Durable Object は一意の名前を持ち、名前ごとにグローバルで 1 インスタンスだけ存在する特別な種類の Worker です。そのインスタンスには SQLite データベースが紐づき、Durable Object が実行されるマシンのローカルディスク上に存在します。これによりストレージアクセスは事実上ゼロレイテンシになります。
では、AI に Durable Object 用のコードを書かせ、それを Dynamic Worker で実行したい、ということになるかもしれません。ではどうすればよいでしょうか?
課題
通常、Durable Objects を使うには次の手順が必要です。
- DurableObject を拡張するクラスを書く。
- それを Worker のメインモジュールからエクスポートする。
- Wrangler の設定でそのクラス用のストレージをプロビジョニングするよう指定する。
- これにより、着信リクエストを処理するクラスを指す Durable Object namespace が作成される。
- Durable Object namespace バインディングを宣言(または ctx.exports を使う)して、Durable Object へリクエストを送る。
これらは Dynamic Workers には自然には当てはまりません。まず明らかな問題はコードが動的であることです。Cloudflare API を呼ばずにコードを実行します。しかし Durable Object のストレージは API 経由でプロビジョニングされ、namespace は実装クラスを指している必要があり、Dynamic Worker 自体を直接指すことはできません。
さらに深い問題として、たとえ Durable Object namespace を動的 Worker に向けられるようになったとしても、それが望ましいでしょうか?エージェントやユーザーに無制限に Durable Object を作らせたいですか?世界中に分散した無制限のストレージを使わせたいですか?おそらくそうではありません。作成数の制限や追跡、あるいは一つのオブジェクトに制限する(個人向けの小さなアプリには十分)、ログや可観測性、メトリクス、課金といった制御を加えたいはずです。
これを実現するには、Durable Object へのリクエストをまずプラットフォーム側のコードで受けて "ロジスティクス"(認可、ロギング、メトリクス、課金、作成数制御など)を行い、その後エージェントのコードへ転送する必要があります。各 Durable Object にスーパーバイザーを実行させたいのです。
解決策:Durable Object Facets
本日、オープンベータとしてこの問題を解決する機能を公開します。Durable Object Facets を使うと、Durable Object クラスを動的にロードしてインスタンス化しつつ、そのクラスに SQLite データベースを提供できます。
Facets の概念は次のとおりです。
- 普通に Durable Object namespace を作成し、あなたが書くクラスをポイントさせます(このクラスがスーパーバイザーになります)。
- そのクラス内でエージェントのコードを Dynamic Worker としてロードし、呼び出します。
- Dynamic Worker のコードは直接 Durable Object クラスを実装してエクスポートできます(つまり、extends DurableObject と宣言されたクラスをエクスポート)。あなたはそのクラスを自分の Durable Object の "facet" としてインスタンス化します。
- facet には独自の SQLite データベースが与えられ、通常の Durable Object ストレージ API を通じて利用できます。このデータベースはスーパーバイザーのデータベースとは分離されていますが、同じ Durable Object の一部として一緒に保管されます。
動作例
以下は、Durable Object クラスを動的にロードして実行するアプリプラットフォームの簡単で完全な実装例です。
import { DurableObject } from "cloudflare:workers"; // For the purpose of this example, we
この例についてのポイント:
- AppRunner はプラットフォーム開発者(あなた)が書く「通常の」Durable Object です。各インスタンスが 1 つのアプリケーションを管理します。アプリのコードを保存し、オンデマンドでロードします。
- アプリ自身は Durable Object クラスを実装し、プラットフォームはそのクラス名が App であることを期待しています。
- AppRunner は Dynamic Workers を使ってアプリコードをロードし、そのコードを Durable Object Facet として実行します。
- 各 AppRunner インスタンスは 2 つの SQLite データベースを持つ 1 つの Durable Object で構成されます:親(AppRunner)用と facet(App)用です。これらのデータベースは分離されており、アプリは自分のデータベースのみアクセスできます。
実行方法
上記のコードを worker.js にコピーし、以下の wrangler.jsonc と組み合わせてローカルで npx wrangler dev を実行します。
"compatibility_date": "2026-04-01",
"main": "worker.js",
"migrations": [
{
"tag": "v1",
"new_sqlite_classes": [
"AppRunner"
]
}
],
"worker_loaders": [
{
"binding": "LOADER",
},
],
}
利用開始
Facets は Dynamic Workers の機能で、Workers Paid プランのユーザー向けにベータで即時利用可能です。Dynamic Workers と Facets に関する詳細はドキュメントを参照してください。
Cloudflare の connectivity cloud は企業ネットワーク全体を保護し、顧客がインターネットスケールのアプリケーションを効率的に構築するのを支援し、あらゆるウェブサイトやインターネットアプリケーションを高速化し、DDoS 攻撃から守り、ハッカーの脅威を低減し、Zero Trust への道を支援します。無料のアプリを使ってインターネットをより速く安全にするには、任意のデバイスから 1.1.1.1 を訪れてください。
より良いインターネットを作るという我々のミッションの詳細はここから始めてください。キャリアの新しい方向性を探している場合は、オープンポジションもご覧ください。
Tags: server-island-start Developer Platform Developers Agents Week Cloudflare Workers Durable Objects Storage