インフラ構成
実査機能 新基盤のインフラ構成。コンピュート=Cloudflare(常駐ゼロ・全て従量)/データ永続=AWS 東京(国内保管)/メディア・データ配信=LiveKit Cloud のハイブリッド構成を採用する。開発への展開は開発プラン Phase 0 を参照。
1. 決定サマリ
| 領域 | 決定 | 備考 |
| 基盤コア API | 採用 Cloudflare Workers(Hono + @hono/zod-openapi + Prisma 7) | エントリポイント4種(fetch / queue / workflows / scheduled) |
| DB | 採用 AWS Aurora Serverless v2(PostgreSQL・東京) | min 0.5 ACU 常時。見送り D1(レジデンシ・トランザクション制約) |
| DB 接続 | 採用 Hyperdrive → 公開エンドポイント直結 | SG=Hyperdrive 公開 IP レンジのみ + TLS verify-full |
| オブジェクトストレージ | 採用 AWS S3(東京) | 録画・handout(文字起こし本文は Aurora 行内 result_json・As-Is 踏襲)。不採用 R2(リージョン保証不可) |
| W1〜W6 配信 | 採用 Cloudflare Queues + DLQ | リトライ・DLQ 組み込み |
| 録画→文字起こし | 採用 Cloudflare Workflows | ステップ実行(ステップごとに結果を永続化し、失敗時は失敗ステップから再開)・ステップ単位リトライ |
| 定期実行 | 採用 Cron Triggers | リコンサイルバッチ |
| チャット | 採用 LiveKit データチャネル再利用(サーバー権威型) | 不使用 独自 WS サーバー・Durable Objects |
| ルーム SPA | 採用 Vite + React SPA + Workers Assets 配信 | SSR 不要(OpenNext / Next.js は不採用) |
| 管理画面(開発者向け) | 採用 Refine SPA on Workers(Workers Assets)+ Cloudflare Access | コアの内部プロキシ /internal/admin 経由・ApiKey 非露出(開発プラン §1.4)。ルーム SPA・コアと同じ Workers 系ツールチェーンに統一(Pages は不使用) |
| メディア | 外部 LiveKit Cloud(SFU + Egress・Ship プラン) | 録画は video composite(合成1本)・Egress は S3 東京へ直書き |
| AI モデレーター | 外部 LiveKit Managed Agent Hosting | lk agent deploy。自前の Agent 基盤を持たない |
| 文字起こし AI | 外部 Azure Speech / OpenAI Whisper / ElevenLabs | Workflows から REST 呼び出し・VTT 出力 |
| オブザーバビリティ | CF ネイティブ(Traces / Workers Logs / Analytics Engine)+ @sentry/cloudflare(Team プラン) | 外部集約先(Grafana Cloud 等)は導入しない。実装方法は オブザーバビリティの Cloudflare 補遺が正 |
| minedia-www | 既存 現行インフラのまま(Rails) | REST(ApiKey)で呼び出し・W1〜W6 受信。Phase 5 でレーンB改修 |
2. 全体構成図
主要フロー
- 入室: ブラウザ → SPA → 基盤コア(参加 JWT 検証 → RoomPolicy → LiveKit トークン発行)→ LiveKit へメディア直結。映像・音声は Cloudflare を通らない
- チャット/ルームイベント(サーバー権威型): 送信=ブラウザ → コア Worker の HTTP ingest(RoomPolicy 認可 → Aurora 永続化 → 宛先算出)→
RoomServiceClient.sendData → LiveKit データチャネルで配信。受信=DataReceived。クライアント直送は不可(canPublishData 全ロール false)。後入室・リロード時は履歴 API(GET /rooms/{id}/chat-messages)で補完
- 録画: LiveKit Egress → S3 東京へ直書き → webhook → Workflows が文字起こしをステップ実行 → W6 配信
- W1〜W6: 基盤コア → Queues(リトライ・DLQ)→ minedia-www へ署名付き配信
- DB: 基盤コア → Hyperdrive(接続プール)→ Aurora 公開エンドポイント。書き込み RTT は Smart Placement(Worker を東京近傍で実行)で圧縮
- 録画視聴:
download-url API で presigned URL を発行し S3 から直接配信
3. 技術スタック
3-1. Worker 構成(デプロイ単位)
Worker は「プロセス」ではなくデプロイとアクセス制御の境界で切る。1 Worker は複数ハンドラ(fetch / queue / scheduled / Workflow クラス)を同居できるため、基盤コアの非同期処理は分割しない。
| Worker | 中身 | 分割理由 |
① 基盤コア(apps/core) | Hono(fetch)+ Queues consumer + Cron + Workflows + 内部プロキシ /internal/admin | API 契約と非同期処理が同じ Prisma スキーマ・RoomPolicy を共有。Smart Placement はこの Worker のみ有効化 |
② ルーム SPA(apps/interview-room) | Workers Assets(静的配信) | UI は API と独立したデプロイ頻度。配信はエッジ最寄り |
③ 管理画面(apps/admin) | Workers Assets(Refine SPA) | Cloudflare Access を被せる境界を公開物と分離 |
ドメインは Worker 単位に割り当て(例: api.* → ①、room.* → ②、admin.* → ③ + Access)。管理画面 → コアは Service Bindings で内部接続(公開ホップなし・CORS 回避)。負荷特性が分かれた場合、queue consumer / Workflows は後から④として分離可能(wrangler.jsonc を分けるだけ)。
🔗
Service Bindings とは: Worker 同士をネットワークを介さず直接呼び出す Cloudflare の仕組み。呼び出し側の wrangler.jsonc に "services": [{ "binding": "CORE", "service": "interview-core" }] と宣言すると env.CORE.fetch(request) で相手 Worker を呼べる。見た目は fetch だが実際は同一スレッド上での直接実行のため、公開 URL への出戻り(DNS・TLS・エッジ再入場)が発生しない。ブラウザは管理画面のオリジンとしか通信しないため CORS 設定も不要。コアの /internal/admin は Service Bindings 経由でのみ到達可能にでき、公開インターネットに管理 API の入口を持たない。
apps/core/ ← 基盤コア Worker
wrangler.jsonc ← bindings: Hyperdrive / Queues / Analytics Engine / Rate Limiting
src/index.ts ← export default { fetch, queue, scheduled } + Workflow クラス
src/api/ ← Hono(@hono/zod-openapi ルート定義・ミドルウェア)
src/queue/ src/workflows/ src/cron/ src/lib/
prisma/schema.prisma
apps/interview-room/ ← ルーム SPA
apps/admin/ ← 管理画面(Refine)
packages/contracts/ ← zod スキーマ・生成 openapi.yaml・API 型(全アプリで共有)
3-2. 基盤コア(apps/core)
| 領域 | 採用 | 備考 |
| HTTP / 契約 | hono + @hono/zod-openapi | ルート定義=zod スキーマ=OpenAPI の単一ソース(G1 の実体) |
| OpenAPI UI | @scalar/hono-api-reference | 確定。コア Worker の /docs ルートに Scalar UI をミドルウェアとしてマウント(app.doc() の OpenAPI 出力をそのまま参照、別ホスティング不要) |
| ORM | prisma 7 + @prisma/adapter-pg | Hyperdrive 経由。prisma migrate は CI から TCP 実行 |
| JWT | jose | EdDSA 署名・/.well-known/jwks.json 公開(jsonwebtoken は EdDSA 非対応) |
| LiveKit | livekit-server-sdk | AccessToken / RoomServiceClient.sendData(チャット配信)/ Egress / WebhookReceiver。Workers 実機確認は P0 スパイク |
| S3 | aws4fetch | SigV4 の presign / put(@aws-sdk より軽量) |
| ApiKey 照合 | bcryptjs + crypto.subtle.timingSafeEqual | truffle-survey-v2 と同系 |
| バリデーション | zod(packages/contracts で共有) | |
| ログ / 監視 | 構造化 console(JSON → Workers Logs)、cloudflare:workers tracing API、Analytics Engine writeDataPoint、@sentry/cloudflare(tracesSampleRate: 0) | 標準 OTel SDK は Workers 非対応(オブザーバビリティの Cloudflare 補遺 §2) |
| テスト | vitest + @cloudflare/vitest-pool-workers、convention test | workerd 実ランタイムでテスト。convention は truffle 移植(エンベロープ形式 / 全ルート認証必須 / ルート網羅 / no-floating-promises) |
3-3. ルーム SPA(apps/interview-room)
| 領域 | 採用 | 備考 |
| フレームワーク | Vite + React SPA + Workers Assets(確定) | SSR 不要のため OpenNext / Next.js は不採用 |
| WebRTC | livekit-client + @livekit/components-react / -styles | 参加者タイル・デバイス制御・画面共有 |
| 接続テスト | livekit-client 同梱の ConnectionCheck | signaling / webrtc / turn / reconnect / publish(P4 の自前計測画面の中核) |
| API クライアント | openapi-typescript + openapi-fetch | packages/contracts の型で契約を FE でも強制 |
| 状態管理 | @tanstack/react-query(サーバー状態)/ zustand(UI 状態) | |
| UI / 監視 | Tailwind CSS / @sentry/react | |
3-4. 管理画面(apps/admin)
Refine(React)+ Vite を Workers Assets で配信し、Cloudflare Access(Zero Trust)でゲート。データ取得は基盤コアの内部プロキシ /internal/admin 経由(Cf-Access-Jwt-Assertion 検証・テナント ApiKey 非露出)。API クライアントは SPA と同じ openapi-fetch を共有。
3-5. 開発ツールチェーン
| 領域 | 採用 |
| モノレポ | pnpm workspace(apps 3つ + packages/contracts) |
| デプロイ | wrangler(environments で dev / stg / prd、wrangler types で Env 型生成、wrangler secret put。DB 資格情報は AWS Secrets Manager) |
| CI/CD | GitHub Actions: typecheck / lint / test / prisma migrate / wrangler deploy |
| OpenAPI | 生成 yaml を redocly lint、UI 配信は Scalar(@scalar/hono-api-reference・確定)、@stoplight/prism-cli モック(レーンB の G2 前先行着手用) |
| Lint | ESLint(no-floating-promises 必須)+ Prettier |
3-6. minedia-www 側(レーンB・Phase 5)
| 領域 | 採用 |
Core::ApiClient | faraday + faraday-retry(ApiKey 認証・Idempotency-Key・リトライ。既存 faraday_middleware 1.x 系との共存に注意) |
| 契約テスト | committee(Prism モックに対して G2 前に先行実装) |
| W1〜W6 受信 | OpenSSL::HMAC 署名検証(標準ライブラリ)・イベント id dedup。非同期処理・通知は既存流用(Sidekiq / Twilio / SES / OneSignal) |
4. Cloudflare 軸の根拠
評価軸: ①アイドル時固定費最小(サーバーレス徹底)②運用対象最小③データレジデンシ(国内保管の一貫説明)。コスト差は月数十ドル=人件費数時間分であり決め手ではない。
- 常駐コンポーネントがゼロになる: API(Workers)・キュー(Queues)・パイプライン(Workflows)・定期実行(Cron)のすべてがマネージドかつ従量。チャット配信も LiveKit データチャネルに相乗りするため独自 WS サーバーを持たない。DB 接続も Hyperdrive から Aurora の公開エンドポイントへ直結するため、「自前で面倒を見るプロセス」が文字通り 0 になる
- コールドスタート実質ゼロ: Workers は isolate モデルで復帰 ~数ms・自動水平スケール。予約制インタビューの体感遅延源が存在しない(Aurora は min 0.5 ACU 常時でウォーム)
- 重い処理は Workers を通らない: 映像・音声は LiveKit 直結、静的アセットはエッジ配信。Workers が処理するのは短命 HTTP(認可・書込・webhook)のみで、128MB/isolate・同時接続 6 の制約は業務特性上ボトルネックにならない
5. 月額コスト試算
規模前提(Medium): 月200インタビュー×60分・全件録画60分・180日保管(定常在庫 ~1.2TB)・視聴転送 ~400GB/月・AI モデレーター比率 30%。LiveKit 費は #5317 の既存試算を使用(7人/セッション=publisher 2 + subscriber 5・720p ≈2Mbps・録画前提・¥160/USD)。オーダー把握用であり、規模実値の確定後に精緻化する。
5-1. ホスティング層(クラウド請求額)
| 項目 | 月額 | 算定前提 |
| Workers Paid | $5 | 基本料。動的リクエスト実勢 月5〜10万件(チャット ingest 含む)は包含枠(10M req・30M CPU-ms)内 |
| Queues / Workflows / Cron | ~$0 | W1〜W6 は月数千メッセージ=無料枠内。Workflows は Workers 従量に包含 |
| Hyperdrive / Smart Placement / Rate Limiting / Access | $0 | Workers Paid 込み・無料枠内(Access は 50 ユーザーまで無料)。静的アセット配信(ルーム SPA・管理画面)は Workers Assets で無料 |
| Workers Logs / Traces / Analytics Engine | $0 | ~22万イベント/月 ≪ 包含枠 2,000万(オブザーバビリティ補遺の試算) |
| Cloudflare 小計 | ~$5 | |
| Aurora Serverless v2 | ~$73 | compute 0.5 ACU×730h×$0.15 ≈ $55 + storage 50GB×$0.12 ≈ $6 + I/O ~50M req×$0.24/M ≈ $12 |
| S3 保管 | 未定 | 現行の実利用量を調査後に反映 |
| S3 視聴転送 | 未定 | 同上(視聴のたび発生・感度大) |
| AWS 小計 | ~$73 + S3(未定) | |
| ホスティング計 | ~$78 + S3(未定) | |
5-2. 監視
| 項目 | 月額 | 備考 |
| Sentry | ~$26 | Team プラン(確定)。traces / logs は CF ネイティブで完結し、外部集約先(Grafana Cloud 等)は導入しない |
| 計 | ~$26 | |
5-3. 外部 SaaS(クラウド選定と独立・参考)
| 項目 | 月額 | 備考 |
| LiveKit Cloud(Ship・録画込) | ~$507(≈¥81,200) | 基本 $50 + 下り転送 (2,160GB−250GB)×$0.12 ≈ $229 + 合成録画 (12,000分−600分)×$0.02 ≈ $228。接続分 84,000 分は無料枠 150,000 分内で $0(#5317 試算) |
| AI(OpenAI Realtime 30% + STT) | 未定 | 現行の実利用量を調査後に反映 |
| 計 | ~$507 + AI(未定) | |
5-4. 総計・感度
| 月額 |
| ホスティング + 監視 | ~$104 + S3(未定) |
| 外部 SaaS 込み総計(確定分) | ~$610 + S3・AI(未定) |
📉
感度・削減レバー: 規模実値(インタビュー数・参加者数に概ね線形)。S3・OpenAI は現行実測の調査後に反映(§6)。
6. 未決事項(Phase 0 で確定)
| # | 事項 | 対応 |
| 1 | 規模実値による試算精緻化 | 現行 minedia-www の実測値で更新(S3・OpenAI 利用料の実測を含む) |
7. 経緯資料
- D1 採用評価(
docs/interview-app-poc/d1-database-assessment.md)— 見送り。Aurora 東京でレジデンシ・トランザクション懸念を解消
- オブザーバビリティ — 監視設計(Cloudflare での実装方法を含む)
本ページは実査機能 新基盤のインフラ構成です。構成図・根拠・コスト試算・未決事項を整理しています。