multi-tenant-platform-architecture について
Multi-Tenant Platform Architectureは、CloudflareまたはVercel上のマルチテナント構成を設計するスキルです。プラットフォーム別にテナント識別、分離、ルーティング、ドメイン管理を案内し、成果物と確認項目も示します。
主な機能
- 01CloudflareまたはVercelの方式選定
- 02テナントのドメインと識別方法の計画
- 03テナント分離とリクエストルーティングの設計
- 04テナントコンテキストの伝達とバインディングの制限
- 05カスタムドメインと静的ファイルの計画
- 06設計成果物とチェック項目の整理
活用シーン
- 01共有アプリのマルチテナント設計
- 02信頼できないコードを実行するテナントの分離計画
- 03テナントのカスタムドメイン導入手順の策定
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ mblode/ agent-skills --skill multi-tenant-platform-architectureインストール後、Claude Code で/multi-tenant-platform-architectureを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
agents/openai.yamlreferences/cloudflare-platform.mdlimits-and-quotas.mdpsl.mdvercel-domains.mdvercel-platform.md詳細
マルチテナントプラットフォームアーキテクチャ(Cloudflare・Vercel)
ワークフロー(順番が重要です)
- プラットフォームを選択する
- Cloudflare:テナントごとのコード分離には Workers for Platforms とディスパッチ名前空間を使用します。テナントが信頼できないコードを実行する場合や、D1/KV/DO のプリミティブを使ったエッジファーストのコンピューティングが必要な場合に最適です。
- Vercel:共有アプリでのマルチテナンシーには、Next.js App Router と Middleware を使用します。テナントが単一のコードベースを共有し、ISR、React Server Components、マネージドデプロイが必要な場合に最適です。
- どちらか一方を選び、ホスティングを混在させないでください。以降の手順は、参照ファイルに記載されたプラットフォーム固有のガイダンスを除き、どちらにも適用されます。
- 選択後は、Cloudflare と Vercel を明示的に比較する場合を除き、そのプラットフォームの参照ファイルのみを読み込んでください。
- ドメイン戦略を選択する
- すべてのサブドメイン/カスタムホスト名には、ブランドドメインとは別の専用テナントドメインを使用します。レピュテーションは分離されません。
random.acme.com上のフィッシングサイトはドメイン全体に損害を与えます。 - テナントのワークロード用に別の TLD を登録します(例:テナント用に
acme.app、ブランド用にacme.com)。 - ブラウザーの Cookie 分離には PSL を検討してください。ただし、レピュテーションは保護されません。psl.md を参照してください。
- PSL への申請は早めに始めてください。審査には数週間かかる場合があります。
- テナント識別戦略を選択する
- サブドメインベース:
tenant.yourdomain.com。ワイルドカード DNS が必要です。多数のテナントに最も簡単な方法です。 - カスタムドメイン:テナントが独自のドメインを用意し、プラットフォームを指す CNAME を設定します。本格的なテナントや有料テナントに最適です。
- パスベース:
yourdomain.com/tenant-slug。テナントごとの DNS/SSL は不要ですが、ブランディングに制約があり、Cookie 分離が複雑になります。 - 主となる戦略を 1 つ選び、アップグレード手段としてカスタムドメインを提供します。
- 分離モデルを定義する
- Cloudflare:信頼できないコードには、テナントごとの Workers を優先します(Workers for Platforms のディスパッチ名前空間)。コードとデータを完全に管理していない限り、複数テナントで共有する分岐処理は避けてください。
- Vercel:
tenant_idスコープを適用した、単一の共有 Next.js アプリを使用します。Middleware がホスト名からテナントを特定し、すべてのデータクエリにテナントコンテキストを含めます。多層防御には Postgres RLS を使用します。
- トラフィックを確定的にルーティングする
- Cloudflare:プラットフォーム Worker がルーティングを担います。ホスト名 -> テナント ID -> ディスパッチ名前空間 -> テナント Worker の順に処理します。マッピングが存在しない場合は 404 を返します。
- Vercel:Next.js Middleware がホスト名を抽出し、URL を
/domains/[domain]の動的セグメントに書き換えます。ミリ秒未満のテナント検索には Edge Config を使用します。マッピングが存在しない場合は 404 を返します。 - どちらのプラットフォームでも、テナントがルーティングを制御したり、他のテナントを認識したりすることはありません。
- スタック全体にテナントコンテキストを渡す
- Cloudflare:プラットフォーム Worker がテナントを特定し、テナント Worker にディスパッチする前にヘッダーまたはバインディングを注入します。
- Vercel:Middleware が転送リクエストのヘッダーに
x-tenant-id、x-tenant-slug、x-tenant-planを設定します。Server Components はheaders()を介して読み取り、API ルートはリクエストヘッダーから読み取ります。 - Middleware/プラットフォーム Worker を唯一の信頼できる情報源とし、クライアントから送信されたテナント ID を決して信頼しないでください。
- 必要なものだけをバインドする
- Cloudflare:テナントごとに最小権限のバインディング(DB/ストレージ/制限付きプラットフォーム API)を設定し、共有グローバル状態を設けないでください。新しいバインディングは明示的な変更として扱い、アクセス権を付与するには再デプロイしてください。
- Vercel:テナント設定(ドメインマッピング、機能フラグ、プラン情報)には Edge Config を使用します。ドメイン管理には Vercel SDK(
@vercel/sdk)を使用します。データベース接続はtenant_idでスコープするか、テナントごとにデータベースを分けます(Neon)。
- カスタムドメインをサポートする
- DNS の接続先を提示し、所有権を確認してマッピングを保存し、ホスト名でルーティングします。
- Cloudflare:カスタムホスト名とマネージド証明書には Cloudflare for SaaS を使用します。cloudflare-platform.md を参照してください。
- Vercel:プログラムによるドメインの CRUD と Let's Encrypt の自動 SSL には、
@vercel/sdk経由で Vercel Domains API を使用します。ワイルドカードサブドメインには Vercel のネームサーバーが必要です。vercel-domains.md を参照してください。 - カスタムドメインを使うとレピュテーションはテナント側に移り、自然なユーザー層が形成されます(プラットフォームのドメインを使うカジュアルなユーザーと、独自ドメインを使う本格的なユーザー)。
- テナントごとの静的ファイルを配信する
robots.txt、sitemap.xml、llms.txtはテナントごとに変える必要があります。/publicから配信しないでください。- Cloudflare:テナント Worker でテナントごとのレスポンスを生成します。
- Vercel:ドメインセグメントごとにルートハンドラーを使用します。vercel-platform.md を参照してください。
- 制限をプランとして提示する
- プラットフォームの制限を料金プランに対応付け、API と UI で公開します。
- リクエスト内で長時間実行されるジョブを処理せず、キュー/ワークフローを使用します。
- 制限のスナップショットと参照元リンクについては、limits-and-quotas.md を参照してください。
- アーキテクチャや料金に関する最終決定の前に、公式ドキュメントで制限を再確認してください。
- API をプロダクトの中心にする
- すべて HTTP 経由で動作し、UI は運用/インシデント対応/請求に使用します。
- プラットフォームのロジックはルーティング層(ディスパッチ Worker または Middleware)に置き、テナントのコンテンツでリクエストを処理します。
- UI でしか動作しない場合、プラットフォームの責務が漏れています。
- 境界を壊さずに拡張する
- キュー/ワークフロー/コンテナをオプションのモードとして追加します。
- ルーティングを明示的に保ち、分離を維持します。
成果物
- プラットフォーム選択の根拠:Cloudflare と Vercel の比較と正当化
- テナント識別戦略:サブドメイン、カスタムドメイン、パスベースのいずれか
- ドメインマップ:ブランドドメインとテナントドメイン、PSL 方針、カスタムドメインのフロー
- 分離計画:テナントごとの Worker、またはテナントスコープを適用した共有アプリ
- ルーティング計画:ホスト名の検索、ディスパッチ/書き換えロジック、フォールバック動作
- テナントコンテキストのフロー:ミドルウェア/ヘッダー/DB を通じたテナント ID の伝播方法
- バインディング/設定マトリクス:テナントごとの機能とデータアクセス
- 制限と料金の対応表:プランごとの CPU/メモリ/リクエスト/ドメインの予算
- API の範囲と運用 UI の範囲
読み込む参照資料
- PSL の登録と Cookie の分離に関するガイダンスは必ず読み込みます:psl.md
- プラットフォームが Cloudflare の場合、プラットフォームのプリミティブとルーティングを読み込みます:cloudflare-platform.md
- プラットフォームが Vercel の場合、プラットフォームのプリミティブとルーティングを読み込みます:vercel-platform.md
- プラットフォームが Vercel の場合、ドメイン管理と SSL を読み込みます:vercel-domains.md
- プラットフォームの制限とプランへの対応付けは最後に読み込みます:limits-and-quotas.md
コミット前チェックリスト
- プラットフォームを選定し、その明確な根拠を文書化した
- テナントのワークロードをブランドドメインから分離し、PSL の方針とスケジュールを決定した
- テナント識別戦略を選定し、カスタムドメインへのアップグレード経路を定義した
- 分離モデルを定義した:テナントごとの Worker(Cloudflare)、または共有アプリ+RLS(Vercel)
- ルーティングを一元的な権威あるものとし、テナント情報に依存しないようにした。ディスパッチまたはミドルウェアがすべてのトラフィックを処理する
- テナントコンテキストはミドルウェア/プラットフォーム Worker のみを通じて伝播し、クライアントが提供した ID を信頼しない
- DNS の接続先、検証、証明書のプロビジョニングを含むカスタムドメインのオンボーディングを定義した
- テナントごとの静的ファイル(robots.txt、sitemap.xml)を動的に配信する
- 制限を請求に連動させ、API と UI の機能を一致させた
- 公式ドキュメントに基づいて制限のスナップショットを更新し、計画メモに日付を記載した
コメント
Markdown 対応