テナントオンボーディング設計
このドキュメントの目的
マルチテナントSaaSにおけるテナントのライフサイクル管理を理解し、テナントの作成から削除までの運用設計ができるようになることが目標です。
マルチテナントとは何かでは「マルチテナントの概念」を学びました。本記事では、テナントをどう作り・管理し・削除するかという運用面に焦点を当てます。
具体例について: 本記事ではIDサー ビスを題材にした例(認証ポリシー、セッション設定等)を使用していますが、ライフサイクル管理の設計原則はSaaS全般に共通です。
テナントライフサイクル
状態遷移
テナントは以下の状態を遷移します:
┌─────────────┐
│ Requested │ ← 申請・登録リクエスト
└──────┬──────┘
│ 承認 / 自動プロビジョニング
▼
┌─────────────┐
┌────>│ Active │<────┐
│ └──────┬──────┘ │
│ │ │
│ 再開 │ 一時停止 │ 再開
│ ▼ │
│ ┌─────────────┐ │
└─────│ Suspended │─────┘
└──────┬──────┘
│ 削除要求
▼
┌─────────────┐
│ Pending │ ← データ保持期間
│ Deletion │
└ ──────┬──────┘
│ 保持期間満了
▼
┌─────────────┐
│ Deleted │ ← 物理削除完了
└─────────────┘
各状態の説明
| 状態 | 説明 | 許可される操作 |
|---|---|---|
| Requested | テナント作成が申請された状態 | 承認待ち、情報確認 |
| Active | 通常稼働中 | すべての操作が可能 |
| Suspended | 一時停止中(支払い遅延、ポリシー違反等) | 管理操作のみ、エンドユーザーアクセス不可 |
| Pending Deletion | 削除待ち(データ保持期間中) | データエクスポートのみ |
| Deleted | 物理削除完了 | なし(復元不可) |
状態遷移の制約
許可される遷移:
Requested → Active (承認)
Requested → Deleted (申請却下)
Active → Suspended (一時停止)
Active → Pending Deletion(削除要求)
Suspended → Active (再開)
Suspended → Pending Deletion(削除要求)
Pending Deletion → Deleted (保持期間満了)
禁止される遷移:
Deleted → * (復元不可)
Active → Requested (状態の逆行)
オンボーディングフロー
テナントの登録方法には大きく2つのパターンがあります。
パターン1: セルフサービス登録
エンドユーザーが自分でテナントを作成するモデ ルです。B2B SaaSで広く採用されています。
ユーザー SaaSプラットフォーム
│ │
│ 1. サインアップフォーム送信 │
│ ──────────────────────────────>│
│ │ 2. 入力バリデーション
│ │ 3. テナントID生成
│ │ 4. リソースプロビジョニング
│ │ 5. 管理者アカウント作成
│ 6. ウェルカムメール + 初期設定 │
│ <──────────────────────────────│
│ │
│ 7. 初回ログイン・初期設定 │
│ ──────────────────────────────>│
│ │
メリット:
- ユーザー体験がスムーズ(即座に利用開始)
- 運用コストが低い(人手不要)
- スケーラブル(大量のテナント登録に対応)
デメリット:
- 不正利用のリスク(スパムテナント、悪意ある登録)
- プロビジョニング失敗時の自動リカバリが必要
対策:
- メールアドレス検証
- CAPTCHA
- 利用規約への同意
- レート制限(同一IPからの連続登録制限)
パターン2: 管理者プロビジョニング
SaaS運営者がテナントを手動で作成するモデルです。エンタープライズ向けSaaSで多く見られます。
顧客 営業/CS SaaS管理者
│ │ │
│ 1. 契約・申込 │ │
│ ──────────────────>│ │
│ │ 2. テナント作成依頼 │
│ │ ──────────────────>│
│ │ │ 3. テナント作成
│ │ │ 4. 初期設定
│ │ │ 5. 管理者招待
│ 6. 招待メール │ │
│ <───────────────────────────────────────│
│ │ │
│ 7. 初回ログイン │ │
│ ──────────────────────────────────────>│
│ │ │
メリット:
- 品質管理(不正テナントの排除)
- カスタム設定が可能(契約内容に応じた初期設定)
- 顧客との直接コミュニケーション
デメリット:
- オンボーディングに時間がかかる
- 人手が必要(スケールしにくい)
パターン比較
| 観点 | セルフサービス | 管理者プロビジョニング |
|---|---|---|
| オンボーディング速度 | 数分 | 数時間〜数日 |
| 運用コスト | 低い | 高い |
| 品質管理 | 自動チェックのみ | 人的レビューあり |
| カスタマイズ性 | テンプレートベース | 個別対応可能 |
| 対象 | SMB / スタートアップ | エンタープライズ |
| スケーラビリティ | 高い | 制限あり |
テナントプロビジョニング
プロビジョニングで初期化するリソース
テナント作成時に以下のリソースを初期化する必要があります:
テナント作成リクエスト
│
▼
┌─────────────────────────────────────────┐
│ プロビジョニングパイプライン │
│ │
│ ┌───────────┐ ┌───────────┐ │
│ │ 1. テナント │ │ 2. DB │ │
│ │ レコード │→│ 初期化 │ │
│ └───────────┘ └─────┬─────┘ │
│ │ │
│ ┌───────────┐ ┌─────▼─────┐ │
│ │ 3. デフォ │ │ 4. 管理者 │ │
│ │ ルト設定 │→│ アカウント│ │
│ └───────────┘ └─────┬─────┘ │
│ │ │
│ ┌───────────┐ ┌─────▼─────┐ │
│ │ 5. 通知 │ │ 6. 監査 │ │
│ │ 送信 │→│ ログ │ │
│ └───────────┘ └───────────┘ │
└─────────────────────────────────────────┘
| ステップ | リソース | 内容 |
|---|---|---|
| 1 | テナントレコード | テナントID、名前、プラン、作成日時 |
| 2 | データベース | テナント用テーブル/スキーマの初期化、RLSポリシー設定 |
| 3 | デフォルト設定 | 認証ポリシー、セッション設定、UI設定のデフォルト値 |
| 4 | 管理者アカウント | テナント管理者ユーザーの作成、初期パスワード/招待リンク |
| 5 | 通知送信 | ウェルカムメール、初期設定ガイド |
| 6 | 監査ログ | テナント作成イベントの記録 |
プロビジョニングの信頼性
プロビジョニングは複数ステップにまたがるため、途中で失敗した場合のリカバリ戦略が重要です。
アプローチ1: 同期実行 + ロールバック
BEGIN
1. テナントレコード作成
2. DB初期化
3. デフォルト設定
4. 管理者アカウント
COMMIT
失敗時 → ROLLBACK(全ステップを取り消し)
- シンプルで理解しやすい
- 全ステップがDB操作の場合に有効
- 外部サービス呼び出しがあるとロールバックが困難
アプローチ2: 非同期実行 + 補償トランザクション
1. テナントレコード 作成(status = "provisioning")
2. 非同期でプロビジョニングジョブ投入
3. 各ステップを順次実行
4. 全ステップ成功 → status = "active"
失敗 → 補償処理 + status = "failed"
- 外部サービス呼び出しに対応
- ユーザーに即座にレスポンスを返せる
- 実装が複雑になる
アプローチ3: べき等(Idempotent)リトライ
各ステップをべき等に設計:
- 既に完了済みのステップ はスキップ
- 失敗したステップからリトライ
例:
ステップ1: 完了済み → スキップ
ステップ2: 完了済み → スキップ
ステップ3: 失敗 → リトライ
ステップ4: 未実行 → 実行
- 部分的な失敗からの復旧が容易
- 各ステップの独立性が必要
テナント識別
テナントを識別する方式は複数あります。どの方式を選ぶかはアーキテクチャ全体に影響します。
方式比較
| 方式 | URL例 | メリット | デメリット |
|---|---|---|---|
| サブドメイン | tenant-a.example.com | ユーザーに分かりやすい、DNS/TLSで分離 | ワイルドカード証明書が必要、DNS管理 |
| パスベース | example.com/tenant-a/ | DNS管理不要、証明書1枚 | URLが長い、ルーティング複雑 |
| ヘッダーベース | X-Tenant-ID: tenant-a | URL変更不要、APIに最適 | ブラウザからの直接アクセスが不便 |
| トークンベース | JWTのtenant_idクレーム | URL/ヘッダー不要、認証と一体化 | テナント切り替え時にトークン再発行 |
| カスタムドメイン | login.customer.com | 完全なホワイトラベル対応 | 証明書管理が複雑、CNAME設定必要 |
サブドメイン方式の詳細
最も広く採用されている方式です。
リクエスト: https://tenant-a.example.com/api/users
┌──────────────────────┐
│ DNS │
│ *.example.com → LB │
└──────────┬───────────┘
│
┌──────────▼───────────┐
│ ロードバランサー │
│ Host: tenant-a... │
└──────────┬───────────┘
│
┌──────────▼───────────┐
│ テナントリゾルバー │
│ Host → tenant_id │
└──────────┬───────────┘
│
┌──────────▼───────────┐
│ アプリケーション │
│ tenant_id をコンテキスト│
│ にセットして処理 │
└──────────────────────┘
実装のポイント:
- ワイルドカードDNS(
*.example.com) - ワイルドカードTLS証明書またはSNI
- テナント名のバリデーション(英数字、ハイフンのみ等)
- 予約語の管理(
www,api,admin等)
ヘッダーベース方式の詳細
API中心のアーキテクチャに適しています。
リクエスト:
POST /api/users
Host: api.example.com
X-Tenant-ID: tenant-a
Authorization: Bearer <token>
┌──────────────────────┐
│ APIゲートウェイ │
│ X-Tenant-IDを検証 │
│ + トークンの tenant と │
│ ヘッ ダーが一致するか │
└──────────┬───────────┘
│
┌──────────▼───────────┐
│ アプリケーション │
└──────────────────────┘
セキュリティ上の注意:
- ヘッダー値をそのまま信用しない
- 認証トークン内のテナント情報と照合する
- ヘッダー改ざんによるクロステナントアクセスを防止
テナント削除とデータ保持
削除フロー
テナント削除は即座に物理削除するのではなく、段階的に進めます。
削除要求 データ保持期間 物理削除
│ (30日〜90日) │
▼ ▼
┌──────────┐ ┌──────────────────────┐ ┌──────────────┐
│ 論理削除 │──>│ データ保持 │──>│ 物理削除 │
│ │ │ │ │ │
│ ・アクセス│ │ ・エクスポート可能 │ │ ・全データ削除│
│ 無効化 │ │ ・復元リクエスト受付 │ │ ・復元不可 │
│ ・通知送信│ │ ・自動更新停止 │ │ ・証明書発行 │
└──────────┘ └──────────────────────┘ └──────────────┘
論理削除で無効化するリソース
| リソース | 処理 |
|---|---|
| 認証 | 全セッション無効化、トークン失効 |
| API | テナント宛のリクエストを拒否(HTTP 403) |
| 管理API | テナント管理者のアクセスを無効化 |
| 課金 | 自動更新停止、未使用期間の返金処理 |
| 通知 | テナント管理者へ削除通知メール |