【技術解説】MasterOrderが採用する「Fail Fast原則」と多層防御アーキテクチャの全貌
MasterOrderは 1. セキュリティ → 2. 動作の安定 → 3. 使いやすさ の順で、飲食店の売上と信頼を預かるインフラとして設計されています。本記事は実装(2026-05-29時点)に基づく技術解説です。
本番構成の概要
| コンポーネント | 役割 |
|---|---|
| 来客 Order UI | Cloudflare Pages+CDNで静的配信。お客様のブラウザ |
| Orderサービス | /connect/{店舗} の店舗別ルーティング・テンプレ出し分け |
| API Server | Java 25 / Spring Boot 3.5。認証・セッション・注文・メニュー |
| Redis | アクティブなテーブルセッション・Joinトークン・Pub/Sub(SSE) |
| PostgreSQL | メニュー・注文・権限(3DB分離:メイン/ユーザ/アーカイブ) |
| スタッフ Client | 開席・QR表示・SSE注文一覧・会計 |
都度発行セッション(技術的核心)
スタッフが POST /sessions/create/{shopId} で開席すると、Redisに TableSession(sessionId・PIN・テーブル番号)を保存。任意で Joinトークン を発行。
- 接続A:
/connect?id=…&pass=…+X-Session-PIN - 接続B:
/#join=…→GET /sessions/join/{joinToken}(PINヘッダー不要) - 会計:
POST /sessions/{id}/checkout→ isActive=false、Joinトークン削除 - 同一テーブル未会計時は新規開席不可
※ Index2(Komorebi Premium)はUIテンプレート名であり、Fail Fast層の名称ではありません。
Fail Fast(Filter層での早期遮断)
- FirebaseTokenFilter:スタッフJWTとDB権限の照合→403
- GuestSessionPinRequiredFilter:来客APIでPIN未設定→401。Controller前で遮断
- PIN失敗超過→423ロック、接続APIへIPレート制限
「不正リクエストを厨房プリンタに届かせない」=業務ロジックに入れる前にFilterで止める設計です。
TOCTOU:会計と追加注文の競合
checkoutとsaveOrderが同時に来た場合、Redis分散ロック(sessionId単位)で一貫性を担保。ロック中の注文は解放後に isActive=false を再評価し安全に404。
速度・スケール
- メニュー店舗単位キャッシュ
- SSE+Redis Pub/Subで複数APIインスタンスからスタッフ全員へ通知
- 注文スナップショットで後からメニュー変更しても整合
オフライン耐性
IndexedDBにメニュー・セッション・未送信注文。オフライン時はキャッシュ表示・会計用スタッフQR。復帰時に再送・再同期。
オーナー向け3点まとめ
- 固定QRではなく開席都度発行
- 会計で必ず失効
- 繁忙時もSSE+Redisで注文を取りこぼしにくい