Back to blog
Engineering

AI アプリプラットフォームを丸ごと Cloudflare で動かす

YYuan team2026-07-146 min read

Yuan は、誰でも一言から AI Native アプリを作れるプラットフォームです。そこにはあまり目立たないエンジニアリング上の事実があります。公開サイト、コントロールプレーン、データベース、オブジェクトストレージ、AI エージェントが動くサンドボックス。プラットフォーム全体が Cloudflare の開発者プラットフォーム上で動いています。Kubernetes も自前のクラスタも使っておらず、チームに運用専任のメンバーもいません。

この記事では、なぜこの構成を選んだのか、アーキテクチャはどうなっているのか、期待以上だった点と、私たちをすり減らした点を書きます。最初に明言しておくと、この記事に Cloudflare のスポンサーは付いていません。私たちは単なるヘビーユーザーです。

AI プロダクトの負荷はどんな形をしているか

AI プロダクトを一年運用して、負荷に対する理解が変わりました。従来の Web トラフィックは、安価な小さいリクエストの大量発生です。こちらでは、一度のユーザー操作が数分走るエージェントターンを起動することもあれば、1 行読むだけのこともあります。振れ幅もずっと大きく、SNS で一度言及されればトラフィックは数分で十倍になり、夜にはほぼゼロに戻ります。

ただ、私たちの設計を最も左右したのは別の特徴です。プラットフォームはユーザーに代わって、AI が生成した信頼できないコードを実行します。従来の PaaS は「コードは開発者が書き、レビューされたもの」という前提に立ちますが、AI Native プラットフォームは「動いているロジックのどれもがモデルの即興かもしれない」と仮定するしかなく、分離を土台から組み込む必要があります。

アーキテクチャ

Cloudflare は分離を三つの粒度の原語として提供していて、私たちはその全部を使っています。

  • Workers(V8 isolate):ミリ秒のコールドスタートで、すべてのリクエストパスを担います。Next.js フロントエンドは OpenNext 経由でここで動き、コントロールプレーンは別の独立した Worker です。
  • Durable Objects:サンドボックスごと、アプリのライフサイクルごとに、シングルスレッドでステートフルなコーディネーターが付きます。「グローバルに一意、厳密に直列」という性質が、並行性バグの一群をアーキテクチャレベルで取り除いてくれます。
  • Containers / Sandbox:AI エージェントは本物のコンテナで動きます。何でもインストールでき、何でも実行できて、爆発しても自分の部屋しか壊れません。

データ層は D1(エッジの SQLite)と R2(下り転送料ゼロのオブジェクトストレージ)。コンポーネント間は Service Binding でつながり、公共のインターネットは通りません。

いちばん満足している三つの決定

公開面と特権面を二つの Worker に分けたこと。 公開トラフィックを受ける Worker は、サンドボックス・データベース・ストレージのバインディングを一切持ちません。特権操作はすべて、ただ一本の Service Binding を通ってコントロールプレーン Worker に入ります。生成コードが公開面で RCE を取ったとしても、攻撃者の手元に直接使える資格情報もバインディングも残りません。この保証はトポロジーそのものから来るもので、コードレビューの注意深さには依存しません。

モデルの API キーをコンテナに絶対入れないこと。 エージェントのコンテナには本物の上流 API キーが存在しません。コンテナ内のコードがモデルを呼ぶと、リクエストはプラットフォーム境界でインターセプトされ、資格情報はプラットフォーム側で注入されてから転送されます。生成コードが自分の環境変数を全部ダンプしても、外で使えるものは何も見つかりません。このインターセプトは Sandbox SDK のアウトバウンドフックに乗っていて、自前のプロキシ群を運用せずに済みました。

アプリのサーバーサイドロジックを、動的ロードされる子 isolate で動かすこと。 このロジックは初期にはコンテナで動いていて、コールドスタートは秒単位でした。Worker Loaders(オンデマンドでロードされる隔離 isolate)に移してからは、コールドスタートはほぼ消えました。アプリごとの隔離ランタイムは多くのプラットフォームではインフラプロジェクトですが、ここでは API 呼び出し一つです。

私たちをすり減らした点

公平を期して、これも書きます。

  • D1 には対話的トランザクションがない。 トランザクションを開いて、読んで、考えて、書く、ということができません。原子的な書き込みはすべて一度にコミットするバッチとして組み立てる必要があり、私たちはデータ層を「先に読み、計算し、一度でコミットする」形に書き直しました。後から見れば書き込みパスの見通しは良くなりましたが、移行の数週間はやはり楽しくなかった。
  • Workers は Node ではない。 Next.js エコシステムの多くのライブラリは、足元に Node がある前提で書かれています。OpenNext が本道は舗装してくれていますが、いつかのビルドの深夜に、fs の存在を仮定する依存にぶつかります。この構成を選ぶなら、ランタイム互換性の切り分けを実コストとして予算に入れてください。
  • コンテナのコールドスタートは現実にある。 サンドボックスを初めて起こすときは、イメージを取得しプロセスを起動するので、数秒から十数秒かかります。私たちの答えはレイヤリングです。isolate で動くものは絶対にコンテナに入れない。コンテナは本当にフル Linux が必要なエージェント負荷のためだけに残し、残りはプリウォームでカバーする。

振り返って

このプラットフォームが私たちにくれた最大のものは、既製の原語としての分離です。isolate、Durable Object、コンテナのそれぞれにクリーンな API があり、組み合わせれば、何か月ものインフラプロジェクトなしにマルチテナントの信頼できないコード実行基盤の骨格が組めます。コストの形も助けになりました。従量課金なのでピークに備えた遊休クラスタが要らず、ユーザー数がまだ伸びている途中のプロダクトにはこれが効きます。過小評価されがちな点をもうひとつ挙げると、課金、ログ、デプロイ、シークレット管理が一つのシステムに収まっているので、小さなチームは注意力を接着作業ではなくプロダクトに使えます。

ユーザーに代わって AI 生成ロジックを実行するプロダクトを作っているなら、この路線は真剣に評価する価値があります。Yuan は端から端までこの上で動いていて、その先に何ができるのかは Gallery に並んでいます。

Y
Yuan team
Yuan team
More articles