AI が書いたアプリに専用 DB を!Cloudflare の Durable Object Facets 登場!
やっほー、しぃちゃんだよ! 今日は「AI が書いたアプリに、ちゃんと自分専用のデータベースを持たせちゃう」っていう、わくわくする発表を見つけたから紹介するね。
Cloudflare Blog
なにが発表されたの?
Cloudflare の Blog から、Durable Object Facets(ドュラブルオブジェクト・ファセット)が open beta で登場したよ! これは Dynamic Workers の新しい仕組みで、動的に読み込んだコードに、自分だけの SQLite データベースを持つ Durable Objects をまるっと持たせられるようになったの。
つまり、AI が生成したアプリを、状態を持ったまま安全なサンドボックスの中で動かせるってこと。書いたのは Durable Objects の生みの親でもある Kenton Varda さんだよ。
今までどうだったの?
ちょっと前に発表された Dynamic Workers は、Worker のコードをその場でセキュアなサンドボックスに読み込める機能だったの。中身はコンテナじゃなくて「アイソレート」で、コンテナより 100 倍速く起動して、メモリは 10 分の 1 で済むくらい軽いんだって。だから「使い捨て」にできる。安全な eval() みたいな感じだね。
最初のユースケースは、AI エージェントが数行のコードを書いて 1 回だけ実行してポイっと捨てる、っていう単発の使い方だったの。でも、もし AI に「ちゃんとした小さなアプリ」を作らせたくなったら? カスタム UI があって、状態を長く覚えていてほしいアプリだったら? そこがずっと課題だったんだよね。
storage は Cloudflare の外部 DB(Cloudflare D1 や Hyperdrive 経由の Postgres)を RPC で渡す手もあるけど、Durable Objects の SQLite はローカルディスク上にあって、アクセスがほぼゼロレイテンシなのが魅力。だから「AI に Durable Object のコードを書かせて、それを Dynamic Worker で動かしたい」ってなるよね。
Perhaps, then, what you really want is for your AI to write code for a Durable Object, and then you want to run that code in a Dynamic Worker.
でも普通の Durable Objects は「Cloudflare API を叩いて storage を provision し、namespace を作る」前提の手順が必要なの。動的なコードだとこの段取りが成り立たないし、そもそも AI やユーザーに namespace を好き放題作らせるのは怖いよね。数の制限やログ、課金も自分で握りたいはず。
これで何が変わるの?
Facets は、そこに「監督役(スーパーバイザー)」を挟めるようにしてくれたの!
まず自分で普通の Durable Object クラス(例だと AppRunner)を書いて namespace を作る。そのクラスの中で AI のコードを Dynamic Worker として読み込んで、そのコードが export している Durable Object クラスを、自分の Durable Object の「ファセット(facet)」として起動する。ファセットは自分専用の SQLite データベースをもらえて、普通の storage API で使えるんだよ。
嬉しいのは、リクエストが必ず自分のコード(親)を最初に通ること。だからログ・メトリクス・課金・レート制限・リソース制約を全部自分でかけられる。AI が作るのは使い捨てスクリプトじゃなくて、状態を持った「動くアプリ」になるってわけ。
深く潜ってみよう
仕組みのキモは、親 Durable Object の中で this.ctx.facets.get() を呼ぶこと。名前を付けて、まだ起動してない(またはハイバネートしてた)ときのコールバックで、どのコードを読むか教えてあげるの。
let facet = this.ctx.facets.get("app", async () => {
let worker = this.#loadDynamicWorker();
let appClass = worker.getDurableObjectClass("App");
return { class: appClass };
});
return await facet.fetch(request);
1 つの Durable Object は、名前ごとに複数のファセットを持てるよ(storage 上限の範囲でね)。上の例だと、AppRunner の各インスタンスは 2 つの SQLite データベースでできてるの。親(AppRunner)のぶんと、ファセット(App)のぶん。この 2 つは一緒に保存されるけど中身は隔離されていて、アプリ側は自分の DB しか読めない。親の DB は覗けないから安心だね。
Dynamic Worker を読み込むときに globalOutbound: null を渡せばネットワークアクセスをブロックすることもできるよ。設定は Wrangler にこんな感じで書くの。
{
"compatibility_date": "2026-04-01",
"migrations": [
{ "tag": "v1", "new_sqlite_classes": ["AppRunner"] }
],
"worker_loaders": [
{ "binding": "LOADER" }
]
}
compatibility_date は 2026-04-01 以降が必要。詳しい使い方は Durable Object Facets のドキュメントを見てね。npx wrangler dev でローカルでも試せるよ。
まとめ
- Durable Object Facets が open beta で登場(Cloudflare の Blog 発)
- 動的に読み込んだコードに、自分専用の SQLite を持つ Durable Object を持たせられる
- 親(スーパーバイザー)が全リクエストを最初に通すので、ログ・課金・制限を自分で握れる
- 1 つの Durable Object が親とファセットの 2 つの隔離された SQLite でできていて、アプリは自分の DB しか読めない
- Workers Paid プランで今すぐ使える。
compatibility_dateは 2026-04-01 以降
AI が生成したアプリを、安全に・状態を持たせて動かすプラットフォームを作りたい人にドンピシャの機能だよ。vibe コーディングした個人アプリを 1 人 1 個ずつ配りたい、みたいな夢もこれで叶いそうだね!