OpenAICloudflare2026/04/15 13:00

Rearchitecting the Workflows control plane for the agentic era

要点だけを先に読めるように短く再構成したセクションです。

元記事

Quick Digest

要約

要点だけを先に読めるように短く再構成したセクションです。

openaijamodel: gpt-5-mini-2025-08-07

Workflows 制御プレーンの再設計(エージェント時代対応)

Key Points

  • 50,000並列対応
  • SousChefとGatekeeper導入
  • Engineを真のソースに

Summary

Workflows の制御プレーンを再設計し、エージェント(機械発火・長時間稼働)による大量同時実行に対応しました。新アーキテクチャはスループットと可用性を優先し、Account のボトルネックを解消するために SousChef と Gatekeeper を導入、Engine をインスタンス存在の単一の真のソースにしています。結果として同時実行数・作成レート・キュー容量が大幅に向上しました。

Key Points

  • 実稼働上の新しいスケーリング目標(既存値→新値):

    • 同時実行: 4,500 → 50,000
    • 作成レート: 100/10秒 → 300/秒(アカウント毎)
    • キュー上限(ワークフロー毎): 1,000,000 → 2,000,000
  • アーキテクチャの要点:

    • Engine をインスタンスの真のソースにし、存在確認をホットパスで担保しない設計ミスを排除。
    • Account は最小限のメタデータのみ保持し、同時リクエスト量に上限を設ける。
    • SousChef: アカウント内を分割し、ワークフロー単位でメタデータとライフサイクルを管理(結果的にワークフロー単位の隔離を獲得)。
    • Gatekeeper: SousChef 間で同時実行スロットをリース方式で配布。1秒周期でバッチ化した呼び出しを行い Account への負荷を制御。
    • Durable Object の alarm + バックグラウンドタスクを活用し、作成ホットパスを速く保ちながら確実に Engine を起動。
  • 運用と移行のポイント:

    • V1 の Account DO はそのまま SousChef 相当に変換して段階的かつライブで移行(メタデータ維持、ダウンタイムなし)。
    • インスタンス操作は Engine への直接ホップで低遅延。リストはカーソルページネーションで一貫性向上。
    • SousChef 数が多すぎると呼び出しレート制限や遅延が発生するため、SousChef の数と分散周期をチューニングする必要あり。
  • エンジニア向け実務アドバイス:

    • インスタンスの存在判定は Engine を参照すること(Account のキャッシュに頼りすぎない)。
    • Alarm と再試行の挙動をテストして、DO の eviction に対する堅牢性を確認。
    • モニタリングはキュー長、スロット取得成功率、SousChef ごとのレイテンシに重点を置く。

Impact

高頻度・大量生成されるエージェント駆動ワークロードに対して、スループットと信頼性が改善され、今後の限界引き上げがしやすい柔軟な制御プレーン基盤が整いました。

Full Translation

翻訳

原文の流れを保ったまま読める翻訳セクションです。

openaijamodel: gpt-5-mini-2025-08-07

エージェント時代に向けた Workflows 制御プレーンの再設計

概要

Workflows(マルチステップアプリケーション向けの耐久実行エンジン)を最初に設計したとき、ワークフローはユーザーのサインアップや注文といった人間の操作でトリガーされる想定でした。オンボーディングフローのように、ワークフローは人ごとに1つのインスタンスをサポートすればよく、人間はクリックに限界があります。

しかし実際には負荷とアクセスパターンが定量的に変化しました:人間がトリガーするワークフローは減り、機械が高速で作るエージェント駆動ワークフローが増えています。エージェントが持続的かつ自律的なインフラになり、数時間〜数日ユーザーの代理で動作するようになると、彼らの作業を支えるために耐久性のある非同期実行エンジンが必要になります。

Workflows はまさにそれを提供します:各ステップは独立してリトライ可能で、ヒューマン・イン・ザ・ループの承認でワークフローを一時停止でき、各インスタンスは障害が起きても進行を失わず生き残ります。さらに、ワークフロー自体がエージェントループを実装したり、エージェントを管理・維持する耐久ハーネスとして使われるようになっています。Agents SDK 統合により、エージェントがワークフローインスタンスを起動し、リアルタイムの進行状況を得ることが容易になりました。単一のエージェントセッションが数十のワークフローを起動でき、複数のエージェントが同時に動作すれば数千のインスタンスが数秒で作られます。Project Think の登場を受け、さらに速度は増すと見込んでいます。

これらに対応するため、Workflows 上でエージェントとアプリケーションをスケールさせやすくするために、次をサポートするようになったことを発表します:

  • 50,000 concurrent instances(同時並列実行インスタンス数)、従来は 4,500
  • 300 instances/second created per account(アカウントあたりの作成速度)、以前は 100
  • 2 million queued instances(作成または再起床され、同時実行スロットを待っているインスタンス)/workflow、以前は 1 million

これらの増加に対応するため、利用データと原理から Workflows の制御プレーンを再設計しました。


V1:Workflows の初期アーキテクチャ

ベータ公開時に説明したように、Workflows は当社のデベロッパープラットフォーム上に構築されています。基本的に、ワークフローは一連の耐久ステップで、各ステップは独立してリトライ可能で、タスク実行、外部イベント待ち、または所定の時刻までのスリープが可能です。

export class MyWorkflow extends WorkflowEntrypoint {
  async run(event, step) {
    const data = await step.do("fetch-data", async () => {
      return fetchFromAPI();
    });

    const approval = await step.waitForEvent("approval", {
      type: "approval",
      timeout: "24 hours",
    });

    await step.do("process-and-save", async () => {
      return store(transform(data));
    });
  }
}

各インスタンスをトリガーし、そのロジックを実行し、メタデータを保存するために、SQLite バックエンドの Durable Objects を活用しました。Durable Object は分散システム内の調整とストレージのための単純だが強力なプリミティブです。

制御プレーンでは、Engine(ステップ実行、リトライ、スリープロジックを含む実際のワークフローインスタンスを実行する DO)のように、インスタンスあたり 1:1 の比率でスピンアップする DO もあれば、Account のようにアカウント単位で全ワークフローとインスタンスを管理する単一の Durable Object もありました。

ベータローンチ後、お客様が急速に Workflows をスケールするのを見て喜んだ一方で、アカウントレベル情報をすべて単一の Durable Object に保存することがボトルネックになることも分かりました。多くのユーザーは毎分数百〜数千のインスタンスを作成・実行する必要があり、Account DO に負荷が集中しました。元のレート制限(4,500 同時スロット、10 秒あたり 100 インスタンス作成)はこの限界の結果であり、V1 の制御プレーンではこれらがハードキャップでした。

すべての Account に依存する操作(作成、更新、一覧取得など)は単一の DO を経由する必要があり、高並列負荷のユーザーは Account に対して秒間数千のリクエストを生成し得ました。


V2:高スループットに向けた水平スケール

新バージョンでは、高ボリュームワークフロー向けにあらゆる操作を根本から見直しました。最終目標は、何千/秒のインスタンス作成や、同時に何百万インスタンスが動くような要件にも対応できることです。また、V2 では柔軟に制限を調整できるようにし、V1 のようなハードキャップを撤廃しました。

設計の要点は以下です:

  • あるインスタンスが "存在する" かどうかの真のソースはその Engine であること。
    • V1 ではキューイング前に Engine の存在確認がなく、Engine がまだスピンアップしていない状態でインスタンスがキューされる不整合が発生する可能性がありました。
  • インスタンスのライフサイクルとライブネス機構はワークフロー単位で水平にスケールし、多くのリージョンに分散されること。
  • 新しい Account シングルトンは必要最小限のメタデータのみを保持し、同時要求数に上限不変(invariant maximum)を持つこと。

V2 制御プレーンにはスケーラビリティを改善するための重要な新コンポーネントが2つあります:SousChef と Gatekeeper。

  • SousChef

    • Account の "副指揮" 的役割を持つコンポーネントです。以前は Account がそのアカウント内のすべてのワークフローとインスタンスのメタデータとライフサイクルを管理していました。SousChef は特定のワークフロー内のインスタンスのサブセットを管理します。アカウント内に複数の SousChef を分散させ、それらが Account に効率的に報告することで管理性を高めます。
    • 副次的な利点として、アカウント単位の隔離に加えて、同一アカウント内で per-workflow の隔離も得られます(各 SousChef は特定のワークフローだけを担当するため)。
  • Gatekeeper

    • アカウント内の全 SousChefs に対して同時実行 "スロット"(concurrency limits から派生)を配布するリースシステムです。インスタンス作成時にインスタンスはアカウント内のランダムな SousChef に割り当てられ、SousChef は Account にそのインスタンスのトリガー(スロット要求)を行います。スロットが与えられれば SousChef は実行を開始してそのインスタンスが詰まらないよう責任を持ちます。与えられなければインスタンスはキューされます。
    • Gatekeeper を導入することで Engine が Account を過負荷にしないようにし、SousChef と Account の通信は 1 秒に 1 回の周期で行われます。各周期でスロット要求をバッチするため、1 秒あたりの JSRPC コールは 1 回に抑えられます。これによりインスタンス作成レートが Account をオーバーロードすることを防ぎます(なお、SousChef の数が多すぎる場合は呼び出しをレート制限したり異なる時間帯に分散します)。
    • またこの周期性により、古いインスタンスの公平性(既に起きているインスタンスを新規インスタンスより優先する等)や max-min 公平性を保てます。例えば、インスタンスが再起床した場合は新規作成インスタンスよりスロットの優先度が高くなるべきですが、各 SousChef は自分のインスタンスが詰まらないことを保証します。

このアーキテクチャはより分散化され、したがってスケーラブルです。インスタンス作成時のリクエストパスは次の通りです:

  1. 制御プレーンバージョンをチェック
  2. その場所にワークフローとバージョン情報のキャッシュがあれば利用
  3. なければ Account を問い合わせてワークフロー名、ユニーク ID、バージョンを取得してキャッシュ
  4. 必要最小限のメタデータ(インスタンスペイロード、作成日時)を自身の Engine に保存

では、Engine が制御プレーンに「存在した」と伝えるのはどうするか?それはインスタンスメタデータを設定した後のバックグラウンドで行われます。Durable Object のバックグラウンド操作は縮退やサーバ障害で失敗する可能性があるため、作成のホットパスで Engine に "alarm" を設定します。これによりバックグラウンドタスクが完了しなかった場合でも、アラームがインスタンスを起動させます。

Durable Object のアラームは将来の細かい時刻で DO インスタンスを起こすことができ、少なくとも一回(at-least-once)実行モデルと自動リトライが組み込まれています。この背景タスクとアラームの組合せを多用することで、ホットパスから操作を取り除きつつ確実に処理が行われるようにしています。これにより、インスタンス作成を高速に保ちながら信頼性を損なわないようにできます。

V2 によって得られる主な利点:

  • インスタンス一覧のパフォーマンスが速く、カーソルページネーションと整合的になる
  • インスタンスに対する任意の操作は正確に1回のネットワークホップで済む(直接その Engine に行けるため、応答遅延が最小化される)
  • 同時により多くのインスタンスが正しく(オンタイムで)振る舞っていることを保証でき、遅延があれば修正できる

V1 → V2 の移行

新しい制御プレーンが高負荷に耐えられるようになったあとは、顧客とインスタンスを新システムへ移行する「地味だが重要」な作業が残ります。Cloudflare 程度の規模ではこの "地味" な作業自体が大きな問題になります。Workflows は1年未満で既に数百万インスタンスと数千の顧客を抱えていました。また V1 の技術的負債により、キューに入ったインスタンスに対して Engine DO がまだ作られていないケースがあり、移行はさらに複雑でした。

移行が難しい理由は、顧客はいつでもインスタンスを実行している可能性があり、SousChef と Gatekeeper を既存アカウントに追加しても中断やダウンタイムを起こさないようにする必要があるためです。

最終的に決めた方法は、既存の Account(以降 AccountOld と呼ぶ)を SousChef として振る舞わせることでした。Account DO を保持することでインスタンスメタデータを温存しつつ、その DO を SousChef 用の DO に変換します。つまり既存 DO を永続化したまま、SousChef の機能を注入します。

次のような変更を AccountOld のコンストラクタ末尾に追加しました:

// You might be wondering what's this SousChef class? This is the SousChef DO class!
import { SousChef } from "@repo/souschef";

class AccountOld extends DurableObject {
  constructor(state: DurableObjectState, env: Env) {
    // We added the following snippet to the end of our AccountOld DO's
    // constructor. This ensures that if we want, we can use any primitive
    // that is available on SousChef DO
    if (this.currentVersion === ControlPlaneVersions.SOUS_CHEFS) {
      this.sousChef = new SousChef(this.ctx, this.env);
      await this.sousChef.setup()
    }
  }

  async updateInstance(params: UpdateInstanceParams) {
    if (this.currentVersion === ControlPlaneVersions.SOUS_CHEFS) {
      assert(this.sousChef !== undefined, 'SousChef must exist on v2');
      return this.sousChef.updateInstance(params);
    }
    // old logic remains the same
  }
}

@RequiresVersion<AccountOld>(ControlPlaneVersions.V

(注:上記はソースに示されているスニペットに基づく抜粋です。)

このやり方により、既存アカウントを段階的かつシームレスに V2 の流れに乗せることができました。


まとめ

  • エージェント主導の高頻度・高並列のワークロードに対応するため、Workflows の制御プレーンを V2 へ再設計しました。
  • SousChefGatekeeper の導入により、アカウント単位のボトルネックを解消し、水平スケーリングと公平性を実現しました。
  • Durable Object のアラームとバックグラウンドタスクの併用でホットパスを短く保ちつつ信頼性を確保しています。
  • V1→V2 の移行は、既存の Account DO を SousChef として振る舞わせることでダウンタイムなしに行いました。

これにより、Workflows はエージェント主導の "agentic era" における高スケールなワークロードをサポートできる基盤を手に入れました。