EmDash Buildに見る、Workers for Platformsを使ったマルチテナントWebサイトホスティング
X-tech推進本部 加藤2026年9月28日にCloudflareはEmDash 1.0を発表しました。
EmDashには大きく「EmDash CMS」と「EmDash Build」の2つの要素が含まれています。EmDash CMSは、AstroとTypeScriptをベースにしたCMSで、EmDash Buildは、「EmDash CMSで管理・編集できるサイトを、チャットUIから構築するアプリケーション」です。少しメタ的な感じですね。
ちなみに、EmDash CMSは安定版がリリースされていますが、EmDash Buildはまだアルファ版扱いです。
EmDash BuildはGitHubのコードをそのままホスティングすると、以下のようなページが立ち上がります。

指示を送信すると、エージェントがEmDash CMS用にコンテンツモデルを設計し、さらに仮のコンテンツを登録したうえで、それを表示するAstroのページやコンポーネントまで一気に作成します。
チャットUIからサイトを作る体験はBolt.newやLovableと同じですが、Webサイトだけでなく、EmDash CMSでコンテンツを更新できる制作・編集環境も構築されるというのが特徴的です。
Cloudflareのリリースによると、Webサイトの作成やホスティング製品を開発している企業向けにも設計されているとのことなので、今回はホスティング部分に注目してみたいと思います。
EmDash Buildを支えるCloudflareの機能
ホスティングの仕組みを見る前に、まずは全体の構成を簡単に整理しておきます。EmDash Buildは以下のCloudflareサービスの組み合わせでできています。
| 機能 | EmDash Buildでの役割 |
|---|---|
| Workers | Honoベースの各種APIを提供します。 |
| Workers Static Assets | EmDash Build自体のUIを配信します。 |
| Durable Objects | 会話やプロジェクト、公開状態などを永続的に管理します。 |
| Containers / Cloudflare Sandbox | プロジェクトごとにEmDash CMSとAstroを動かす編集・実行環境を提供します。 |
| Artifacts | ソースコードとローカルCMSの状態をGitリポジトリに保存します。 |
| Workers AI | 音声入力の文字起こしや、次の操作候補の生成に使います。 |
| AI Gateway | サイト構築用のAIモデルを呼び出す窓口として使います。 |
| Workers for Platforms | サイトごとのWorkerを配置し、公開サイトを配信します。 |
| R2 | 公開するファイルなどのリリース成果物を保存します。 |
| D1 | ユーザーのログイン状態や、公開URLに使うサイト名を保存します。 |
| プロキシされたゾーンとホスト名 | EmDash Build本体、プレビュー、公開サイトのアクセス先を用意します。 |
どこに何が使われているかは以下のようなイメージです。

Cloudflareのどの機能をどこで使っているかのイメージ図
※ 実際の画面ではなく、解説のためのイメージ図です。
※ カスタムドメインで公開するにはCloudflare for SaaSへのカスタムホストネームの登録に加え、独自ドメインから対象サイトへ振り分ける処理などを実装する必要があります
Workers for Platformsによるマルチテナントホスティング
ここからが本題です。EmDash Buildでは、Workers for Platformsを使い、複数の利用者のサイトを共通の基盤で管理・配信するマルチテナントホスティングを実現しています。サイトごとにWorkerを分け、それぞれを隔離する構成です。
この構成を簡単に図にすると、以下のようになります。

ホスト名ごとにLive Workerへ振り分けるイメージ図
Workers for Platformsを使ったホスティングについてはCloudflareのドキュメントにも詳しく書かれています。
EmDash Buildを使った公開では3種類のWorkerが登場します。
| Worker | 役割 | 配置する単位 |
|---|---|---|
| Dispatch Worker | すべての公開サイトへの共通の入り口となるWorker。ホスト名に応じて対象サイトのLive Workerへ転送する。 | EmDash Build全体で1つ |
| Live Worker | HTMLや関連リソースを配信するWorker。サイトを更新するときは、Live Workerの中身を更新する。 | サイトごとに1つ |
| Candidate Worker | 新しいリリースをLive Workerへ反映する前に、確認用としてデプロイされるWorker。 | リリースごとに1つ |
Dispatch Workerの処理を簡略化すると、次のようになります。
const site = await resolveSite(new URL(request.url).hostname);
if (!site) return new Response("Not found", { status: 404 });
const liveWorker = env.WFP_DISPATCHER.get(site.liveScriptName);
return liveWorker.fetch(request);
ここでやっているのは、リクエストを受け取ったら、ホスト名から対象となるLive Workerを選び、リクエストを転送するだけです。
このようにDispatch Workerを前段に置くことで、Live Workerを呼び出す前にリクエストの検証を行ったり、Live Workerからのレスポンスを調整できるなどの利点があります。
EmDash Buildからの公開
次は、サイトを公開する流れを簡単に見ていきます。EmDash Buildでは、一度Candidate Workerとしてリリースを作り、チェックに成功したらLive Workerへ反映するようになっています。
- ユーザーが公開ボタンを押すと、EmDash Buildがそのユーザーがプロジェクトの更新権限を持っているか確認する
- EmDash BuildがSandboxでAstroをビルドし、公開時点のHTMLや関連ファイルを生成する
- 生成されたファイル群とWorkerのコードをリリース成果物としてまとめ、R2へ保存する
- EmDash Buildの管理部(コントロールプレーン)がR2から成果物を読み出し、Candidate Workerへ配置する
- コントロールプレーンがCandidate Workerのヘルスチェックを実施
- ヘルスチェックが成功したら、Live Workerの中身を入れ替える
- Live Workerは、Worker自身のStatic Assetsから配信する
ちなみに、ヘルスチェックでは、意図したリリースが配置され、トップページのHTMLを配信できるか、などを確認しているようです。
Live Workerの公開内容を以前のバージョンに戻す場合も、コントロールプレーンがR2に保存された過去の成果物を取り出し、同じLive Workerへ再配置することで実現できます。
セキュリティと権限境界
複数のサイトを同じ基盤にホスティングするため、サイト同士の分離と、公開先を操作する権限の管理が重要になってきます。EmDash Buildでは、次のように扱っています。
- サイト間の分離:各Live Workerは互いに隔離され、別のWorkerへのアクセス権限は与えない
- 公開権限の分離:公開用のAPIトークンはコントロールプレーンだけが保持し、Sandboxやサイト側のWorkerには渡さない
- 公開操作の認可:意図せず別のサイトを更新できないよう、EmDash Buildは操作したユーザーが対象プロジェクトの所有者かを確認する
現状のEmDash Buildではプロジェクトを作成した人のみが公開もできるようになっており、公開権限を別の人にも渡す場合は拡張が必要になります。
おわりに
今回はEmDashの実装をもとにどのような仕組みになっているかを少し整理してみました。
EmDash Buildを使わない場合でも、Workers for Platformsを使って、複数のサイトをまとめて扱いつつ、アクセスの振り分けや公開操作を共通の処理にまとめている点はとても参考になります。何をサイトごとに持たせ、何を共通化するのかを考える具体例になると思いました。
EmDash Build自体はまだアルファ版なので、実践投入はまだ先になりそうですが、今後のアップデートも追ってみたいと思います。