SaaS基盤をAWSで設計するとき、多くのエンジニアが最初にぶつかるのが「テナントをどこまで分離すべきか」という問いです。サイロ型にすれば安全だがコストが跳ね上がり、プール型にすれば効率的だがデータ混在リスクが怖い。そのバランスをどこで取るか、教科書にはなかなか書かれていません。
この記事では、AWSでマルチテナントSaaS基盤を設計するときの核心となる3点——テナント分離パターンの選択・テナント別コスト配賦の実装・スロットリングとクォータ設計——を実装シナリオ別に整理します。各パターンの概念的な比較についてはシングルテナント vs マルチテナント設計入門で解説しているので、本記事はAWSでの具体的な実装判断に絞って進めます。

なぜSaaSのテナント設計はこれほど難しいのか
オンプレミスの受託システム開発では、顧客ごとに専用サーバーを立てるのが当たり前でした。インフラのコスト効率よりも、顧客間の完全分離とカスタマイズ対応が優先されていたためです。
SaaSに転換すると、この前提が一気に崩れます。100テナントに個別EC2を用意すれば固定費が100倍になり収益モデルが成り立たない。かといってDBを完全共有すると、バグや設定ミスで別テナントのデータが漏れる怖さが常につきまといます。
さらに運用フェーズに入ると、次の課題が噴出します。
・テナントAが大量リクエストを送り、全テナントのレスポンスが悪化する(ノイジーネイバー問題)
・どのテナントが赤字でどのテナントが利益を出しているか、AWSの請求書からは読み取れない
・テナントが増えるたびに担当者がDB作成・IAM設定を手動対応している
これらすべての根本は、設計初期にテナント分離の粒度を決め、コスト可視化とスロットリングをアーキテクチャに組み込まなかったことにあります。後から変えようとすると、既存テナントへの影響を避けながら段階的に変更する工数が設計時の10倍以上かかります。
テナント分離3パターンとAWSでの実装判断
1. サイロモデル:テナントごとに専用リソースを割り当てる
各テナントが専用のコンピューティング・DB・ネットワークを持ちます。AWSで最も強い分離を実現するのは「アカウントサイロ」——AWS OrganizationsでテナントごとにAWSアカウントを分ける方式です。
・長所: テナント間のデータ混在リスクがゼロ、FISCやISMAP等のコンプライアンス要件への対応が容易、テナントごとの費用がAWS請求書から自動的に分離できる
・短所: テナント数に比例してコストが増加、稼働率の低いテナントがリソースを遊ばせる、アカウント数増加でOrganizations管理が複雑になる
・向いているケース: 金融・医療・官公庁向け高単価エンタープライズ契約、規制要件上の分離が必要、テナント数が10未満程度
アカウントサイロでは、Service Control Policies(SCP)でリージョン制限や禁止オペレーションを強制できるため、コンプライアンス審査での証拠提出が容易になります。
2. プールモデル:テナントがリソースを共有する
すべてのテナントが同じインフラを共有し、アプリケーションレイヤーでテナントIDによるデータ分離を実施します。
・長所: テナント数増加に対してコストが準線形に伸びる(規模の経済)、インフラ管理がシンプル
・短所: テナントIDの取り違えバグが即データ漏洩につながる、ノイジーネイバー問題が発生しやすい
・向いているケース: SMB向け低価格プラン、テナント数が数百以上の規模
DBレイヤーでの実装は主に2種類あります。
| 手法 | 内容 | 注意点 |
|---|---|---|
| Row-Level Security | 全テーブルにtenant_id列を持ち、アプリ側でWHEREに必ず含める | SQLミスで別テナントデータが参照可能になる |
| スキーマ分離 | PostgreSQL等でテナントごとにスキーマを分割 | スキーマ数が多いとパフォーマンス劣化・マイグレーションが複雑化 |
Aurora PostgreSQLを使う場合、Row-Level Securityをデータベースネイティブ機能として設定することで、アプリバグによるデータ混在を防ぐ多重防御が可能です(2026年9月時点)。
3. ブリッジモデル:プラン別に分離レベルを変える
商用SaaSで最も多いのがこのハイブリッドです。
・Enterpriseプラン→ サイロ(専用AWSアカウントまたは専用DB)
・Standardプラン→ プール(共有Aurora、スキーマ分離)
・Freeプラン→ プール(共有Aurora、Row分離)
低価格帯はプールでコストを抑え、エンタープライズでは専用リソースを提供して高単価を正当化します。
設計上の最重要ポイントは「Row分離で始めてもサイロへ昇格できるデータモデルを最初から用意しておく」こと。後からRow分離をスキーマ分離に移行するとダウンタイムなしには難しく、テナントへの影響が避けられません。テナントIDをプライマリキーの先頭に含める設計(例:DynamoDBのパーティションキーを `{tenant_id}#{entity_id}` にする)が昇格コストを下げます。
テナント別コスト配賦の設計
「どのテナントが利益を出していて、どのテナントがコストセンターか」を把握することは、価格改定・契約交渉・解約防止の根拠になります。
サイロモデル:アカウント分割+Cost Categoriesで自動配賦
アカウントサイロの場合、OrganizationsのAWS Cost CategoriesでアカウントIDをテナント名にマッピングするだけで、自動的にテナント別コストが分類されます。追加実装が不要なのが最大の利点です。
プールモデル:タグ戦略+カスタムメトリクスで按分
プールモデルではリソースが共有されるため、タグ戦略が必要です。ECSタスク定義・Lambda関数・RDSのリードレプリカにリソースタグ(`tenant_id=acme-corp`)を付与し、AWSコンソールでCost Allocation Tagsを有効化することで、Cost ExplorerでのテナントID別コスト表示が可能になります。
ただし、共有のAuroraクラスターやElastiCacheのように単一テナントIDで特定できないリソースは「按分コスト」として扱います。テナント別のAPIリクエスト数や処理時間をCloudWatchカスタムメトリクスで記録し、その比率でインフラ共有費用を割り振る月次バッチが現実的な実装です。
# boto3でテナント別APIリクエスト数をCloudWatchに記録する例(Python) import boto3 cw = boto3.client('cloudwatch', region_name='ap-northeast-1') def record_tenant_request(tenant_id: str, endpoint: str): cw.put_metric_data( Namespace='SaaS/TenantMetrics', MetricData=[{ 'MetricName': 'APIRequestCount', 'Dimensions': [ {'Name': 'TenantId', 'Value': tenant_id}, {'Name': 'Endpoint', 'Value': endpoint}, ], 'Value': 1, 'Unit': 'Count', }] )
このメトリクスをもとに月次レポートを生成することで、テナントへの使用量レポート提供(Usage-Based Pricingの基礎)にも応用できます。
スロットリングとクォータ設計
プールモデルの最大の悩みがノイジーネイバー問題——テナントAが深夜バッチで大量リクエストを送ると、テナントBの本番業務が遅くなるという現象です。これは設計で防ぎます。
Amazon API GatewayのUsage Plansを使う
Amazon API GatewayでAPIを公開している場合、Usage Plans + APIキーでテナント別スロットリングを実装できます。
# AWS CLIでUsage Planを作成(Standardプラン用) aws apigateway create-usage-plan \ --name "standard-plan" \ --throttle burstLimit=100,rateLimit=50 \ --quota limit=10000,period=DAY \ --region ap-northeast-1 # テナントごとにAPIキーを生成してUsage Planに紐付け aws apigateway create-api-key \ --name "tenant-acme-corp" \ --enabled aws apigateway create-usage-plan-key \ --usage-plan-id {PLAN_ID} \ --key-id {API_KEY_ID} \ --key-type API_KEY
この設定で「Standardプランは1日1万リクエスト、バーストは最大100RPS」という制限を実装できます。プランごとにlimit/throttle値を変えれば、Freeプランとエンタープライズプランで異なるクォータを提供できます(2026年9月時点のAPI Gateway料金体系に基づく)。
コンピューティングレイヤーでの追加対策
APIレイヤーより下でも制御が必要な場合は、テナント別にECSサービスを分けるか、Lambda関数のReserved Concurrencyでテナント別の同時実行数を制限するパターンが有効です。
| 手法 | 制御の粒度 | コストへの影響 |
|---|---|---|
| API Gateway Usage Plans | リクエスト数・レート | ほぼゼロ(Usage Plan自体は無償) |
| テナント別ECSサービス | CPU・メモリ上限 | サービス数×管理オーバーヘッド |
| Lambda Reserved Concurrency | 同時実行数の上限 | コールドスタートが増加する可能性 |
| SQSキューをテナント別に分割 | バックグラウンド処理のスループット | キュー数に比例したSQS料金 |
テナント認証・アイデンティティ設計
マルチテナントSaaSで認証を自前実装するのは危険です。JWTの失効処理・ブルートフォース対策・セッション管理を一から作ると脆弱性の温床になります。
AWSでの推奨パターンはAmazon CognitoのUser Poolsを利用し、テナントIDをJWTのカスタムattribute(`custom:tenant_id`)に埋め込む方式です。
User Poolの分割方針は2択です。
・テナントごとにUser Poolを作成(サイロ): テナントA専用のパスワードポリシー・MFA設定が持てる。ただしUser Pool数が増えると管理コストが増加(上限は1アカウントあたり1,000 User Pool)
・単一User Pool + グループ: グループ名をテナントIDに対応させ、JWTの `custom:tenant_id` claimでテナントを識別。インフラはシンプルだがアプリ側の実装コストが高い
どちらの方式でも、バックエンドのすべてのAPIエンドポイントでJWTから`tenant_id`を取得し、DBクエリに必ずフィルターとして含めるミドルウェアを設けることが必須です。この検証を1か所でも省略すると、水平的アクセス違反(Broken Object Level Authorization)が発生します。URLパスやクエリパラメーターのtenant_idは補助情報として扱い、認証の根拠にしないことが原則です。
よくある設計ミスと対処法
【ミス1】テナントIDをURLパラメーターにのみ持つ
`GET /api/data?tenant_id=acme-corp` のような設計では、攻撃者がtenant_idを書き換えるだけで別テナントのデータに触れる可能性があります。テナントIDは必ずJWT claimsから取得し、URLは表示目的に限定してください。
【ミス2】プールモデルでインデックスを後回しにする
`WHERE tenant_id = ? AND created_at > ?` というクエリが頻出するため、`(tenant_id, created_at)` の複合インデックスが不可欠です。テナント数が増えた後でインデックスを追加すると、大規模テーブルへのALTER TABLEによる長時間ロックやストレージ消費増大を招きます。データモデル設計時にアクセスパターンを洗い出し、インデックスを事前に設計することが重要です。
【ミス3】スロットリングを後付けしようとする
「まず全テナント共通でよい、ノイジーネイバーが出てから対応する」という判断は危険です。ノイジーネイバーが発生してから既存テナントへの影響を避けつつスロットリングを導入する工数は、設計時の10倍以上かかります。Usage Plansのデフォルト制限値をゆるめに設定してでも、アーキテクチャに最初から組み込んでおくことを強く勧めます。
【ミス4】テナントオンボーディングを手動運用する
テナントが契約するたびにDB作成・IAMロール設定・User Pool登録を手動で行っていると、テナント数が50を超えた時点で担当者がボトルネックになります。AWS Step FunctionsとTerraform(またはAWS Service Catalog)を使ったセルフサービス型のテナントオンボーディングフローを、スケール前から設計しておくべきです。

本記事のまとめ
マルチテナントSaaS基盤をAWSで設計するときの要点を整理します。
| 設計領域 | 判断基準 | 主要AWSサービス |
|---|---|---|
| テナント分離 | 価格帯・コンプライアンス要件で3パターンを使い分け | Organizations / Aurora / DynamoDB |
| コスト配賦 | サイロはアカウント分割で自動化、プールはタグ+按分 | Cost Categories / Cost Allocation Tags / CloudWatch |
| スロットリング | 最初からUsage Plansを組み込む。コンピューティング層も必要に応じて追加 | API Gateway / Lambda Concurrency / SQS |
| 認証 | tenant_idはJWT claimsから取得、URLパラメーターに依存しない | Amazon Cognito |
| オンボーディング | テナント追加フローを自動化。手動運用は50テナントが上限の目安 | Service Catalog / Step Functions / Terraform |
テナント分離の選択は「後から変えるのが最もコストのかかる設計判断」です。プールモデルで始めるとしても、サイロへ昇格できるデータモデルと認証設計だけは初期段階から用意しておくことを強く勧めます。
PR
AWSクラウド設計完全ガイド(アクセンチュア株式会社/日経BP)
Well-Architectedフレームワークをベースに、マルチテナント設計・コスト最適化・セキュリティ設計まで網羅した実践的な一冊。SaaS基盤設計の判断基準を体系的に学びたいエンジニアに最適です。
