マルチテナントアーキテクチャの理解

その他 未分類

マルチテナントアーキテクチャとは?

「マルチテナントアーキテクチャ」とは、ひとつのソフトウェアやインフラを複数の利用者(テナント)が共有して使う仕組みのことを指します。
たとえばクラウドサービスでは、1つのアプリケーションを何社ものお客さんが同時に使っていても、それぞれのデータや設定はしっかり分かれています。

一般的には、データベースを共通したり、スキーマをどう分けるのか、といった技術的な話が多いですが、今回は、ユーザーからみた機能として、どのようなテナントアーキテクチャにすることがよいのか、有名なSaaSがどういう戦略をとっているのかを理解していきたいと思います。

テナントとは?

  • 法人の管理者がSaaSとサービス利用の契約して
  • 管理者が社員や関係者を招待して
  • その単位でデータや権限が管理される
    そんな「組織としての利用の入れ物」です。

SaaSの比較

Slack

ビジネス向けのチームコミュニケーション(チャット)SaaS。チャンネル中心で会話・ファイル共有・通知連携を行う。

テナントまわり

  • テナント:ワークスペース
  • プロジェクト相当:チャンネル(Public/Private)
  • チーム:チャンネルやユーザーグループで実質的に構成
  • ロール:Workspace Owner / Admin / Member / Guest

利用手順

  1. 管理者がワークスペース作成
  2. メンバーをメール招待 or ドメイン連携で参加
  3. チャンネルを作成(部署別・案件別)
  4. 外部パートナーはGuestで参加(チャンネル限定)

課金

  • 席課金(ユーザー数ベース)。アクティブ課金のプランあり。
  • 上位プランでSAML SSO、監査ログ、保持ポリシーなど。

向き/注意

  • 向き:社内情報をチャンネル外に出さず堅牢に守りたい組織。
  • 注意:ワークスペース間の横断は弱め。社外コラボはGuest運用前提。

GitHub

ソースコードのホスティングと共同開発プラットフォーム。Issue/PR/Actionsで開発フローを管理。

テナントまわり

  • テナント:Organization
  • プロジェクト相当:Repository(+Projects機能)
  • チーム:Org配下のTeamで権限束ね
  • ロール:Org Owner / Member(Repo単位で Read/Write/Admin 付与)

利用手順

  1. 個人アカウントでログイン
  2. Orgを作成しメンバー招待(社内外可)
  3. Repo作成、Teamに権限割当
  4. ブランチ保護・CI/CD( Actions )設定

課金

  • Org単位の席課金+一部機能上位化(Codespaces/Actionsの従量など)。

向き/注意

  • 向き:社外を含むコラボが多い開発組織。個人↔組織をまたぐ働き方。
  • 注意:公開/非公開の切り分け、Teamと権限設計を最初に整理すると運用がラク。

Notion

ドキュメント・データベース・タスクなどを柔軟にまとめるワークスペース。個人→チームへスムーズに拡張できる。

テナントまわり

  • テナント:Workspace(個人/チーム両方あり)
  • プロジェクト相当:ページ/DB(ツリーで自由に構成)
  • チーム:グループ共有(Enterpriseで高度化)
  • ロール:Admin / Member / Guest(ページ単位で権限きめ細かい)

利用手順

  1. 個人Workspaceでスタート(無料でお試し)
  2. チーム導入でメンバー招待、スペース/権限整理
  3. ページ・DBテンプレでナレッジ基盤化
  4. 外部共有はGuest/リンク共有で制御

課金

  • 席課金(個人無料→チーム有料)。上位でSSO、権限・監査が強化。

向き/注意

  • 向き:PLGで自然にスケールさせたいナレッジ系SaaSの参考モデル。
  • 注意:ページ単位の共有設定が柔軟なぶん、権限ポリシーを最初に決めると事故が減る。

Auth0

認証・認可(IDaaS)。アプリ側のログイン/SSO/MFA/ユーザー管理をまるごと任せられる。

テナントまわり

  • テナント:Auth0のTenant(運用空間が完全分離
  • プロジェクト相当:Application(SPA/API/Native などのクライアント定義)
  • チーム:ダッシュボードの管理者グループ
  • ロール:ダッシュボードRBAC(管理権限)+アプリ側のRBACは実装次第

利用手順

  1. Tenant作成(開発/本番を分けることが多い)
  2. Application登録、コールバックURL設定
  3. ルール・アクションでトークンにクレーム付与(例:tenant_id, roles)
  4. IdP連携(Google/AzureAD/Okta)やMFA設定

課金

  • MAU(Monthly Active Users)中心の従量。上位でB2B/Enterprise機能。

向き/注意

  • 向き:B2B SaaSのログイン基盤、SSO/SAML対応が必須な企業向け。
  • 注意:Tenantが完全分離のため、環境・設定の横展開は自動化(IaC)が前提。

Google Workspace

メール(Gmail)、カレンダー、Drive/Docsを含む企業向け生産性スイート。

テナントまわり

  • テナント:Google Workspace ドメイン(example.com)
  • プロジェクト相当:サービス単位のリソース(ドライブの共有ドライブ等)
  • チーム:組織部門/グループ(Google Groups)
  • ロール:Super Admin / Admin / User(サービス別の管理役割も)

利用手順

  1. ドメインで契約・所有確認
  2. ユーザー作成(プロビジョニング)
  3. 組織部門やグループ作成、ポリシー適用
  4. SSO/端末管理/保持ポリシー設定

課金

  • 席課金(ユーザー数)。プランでストレージ・セキュリティ機能が拡張。

向き/注意

  • 向き:企業基盤としてのメール/ストレージ/コラボを統合管理。
  • 注意:ドメイン=テナントなので、社外コラボは共有ドライブ/リンク権限の運用設計が鍵。

ChatGPT

生成AIアシスタントのSaaS。個人利用に加えて、Business/Enterprise/Edu の各プランで組織向けワークスペース(= テナント)を提供し、SSO・RBAC・監査・データ保護などの管理機能を備える。組織データは既定で学習に使われない。

テナントまわり

  • テナント:ChatGPTのワークスペースが単位(Business/Enterprise/Edu)。ドメイン検証、SSO、利用状況の可視化、役割管理に対応。
  • チーム/グループ:ワークスペース配下でメンバーを編成。管理者はSSO・保持・アクセス制御などのポリシーを設定できる。
  • ロールOwner / Admin / Member の3階層(権限はワークスペース管理・請求・設定などに段階化)。
  • データ保護:Enterprise/Business/Edu では入力・出力の所有権は利用者側既定で学習不使用保存時/通信時暗号化

利用手順

  1. 組織のワークスペースを作成(Business/Eduは即時、Enterpriseは営業経由)
  2. SSOドメイン検証を有効化、ユーザーを招待/SCIMで同期
  3. 連携(コネクタやファイル、検索など)と権限・保持ポリシーを設定
  4. GPTsやプロジェクトを共有し、利用状況をダッシュボードで把握(役割に応じてガバナンス)

課金

  • Business(旧Team)席課金。ヘルプ記載では年契 $25/席/月、月契 $30/席/月(2席以上)。
  • Enterprise/Edu:見積もり(SLA、データ保持の細分、データレジデンシー、RBAC拡張などが対象)。
  • 注意APIの課金はChatGPTサブスクと別勘定(同一ではない)。

向き/注意

  • 向き:組織単位での生成AI活用(SSO・監査・RBAC・保持ポリシーが必須なケース)。SOC 2やISO系列の適合、RBACや拡張SSOが求められる企業・学校に向く。
  • 注意:プランで使える管理/セキュリティ機能が異なる(例:SAML SSO・専用ワークスペース・統合請求は Business/Enterprise 以上)。導入前にプラン別機能表を確認する。

ER設計をかんがえてみる

Q1. サインアップは「個人から」? それとも「法人(組織)から」?

モデルA:法人のみ

例:Google Workspace。ドメイン検証、SSO、ユーザー一括管理から開始。
向き:IT主導、規制・監査要件が強い全社導入。

モデルB:個人 → 組織へ昇格

例:Slack、Notion、GitHub、ChatGPT Team/Business。まず個人や小チームで開始、後で組織化。
向き:部門起点で広げたい、低摩擦で試したい。

モデルC:個人も法人でも参加可能

例:Figma、Miro、Airtable、Linear。個人利用も法人導入も両方に対応。
向き:自由度を保ちつつ、スムーズに組織運用へ切り替えたい。

おすすめ:モデルCを基本とする

既定は個人で開始し、「会社のドメインで始める(管理者向け)」も用意しておく。
個人組織から法人組織への移管が可能な設計にしておくと、導入が柔軟になる。

Q2. 組織の中にある単位は「Workspace」か「Project」か「Repository」か?

モデルA:Workspace(部屋・スペース)

例:Slack、Notion、Linear

  • 意味:データ・権限・設定の“まとまり”
  • 特徴:1つの組織に複数のワークスペースが存在する
  • 用途:部門別、目的別、セキュリティ境界などに使い分け
  • UIでの扱い:切り替えが大きく、横断しない前提

モデルB:Project(業務単位)

例:Jira、Asana、Figma

  • 意味:ワークスペースの中にある小さめの業務単位
  • 特徴:目的・期間・担当が定まっている
  • 用途:案件・タスク・議事録・AI出力などの単位に向いている
  • UIでの扱い:Workspace内で一覧表示や検索対象になる

モデルC:Repository(コード単位)

例:GitHub、GitLab

  • 意味:1つのコードベースや構成を管理する単位
  • 特徴:ブランチ・タグ・CI/CDなど技術的要素が強い
  • 用途:ソフトウェア開発が前提
  • UIでの扱い:Projectよりも自己完結・履歴中心

推奨モデル:Workspace+Project(+ Repository は用途次第)

  • OrganizationWorkspaceProject
  • Workspaceが**「部屋」または「チーム」で、Projectが「案件」や「会議体」**
  • リポジトリを持ちたければ、Project配下に紐付け

Q3. 組織外ユーザーをワークスペースやプロジェクトに参加させることはできるか?

モデルA:どちらも不可(完全に組織内のみ)

例:Notion(Enterprise)、ClickUp(制限あり)

  • 組織に招待されていないユーザーは一切アクセス不可
  • SSOやドメイン制限を前提に、ガバナンス・コンプライアンスを重視
  • 外部とのコラボには向かない

モデルB:ワークスペースは不可、プロジェクトはゲストで可

例:Figma、GitHub、Slack

  • ワークスペースは組織内ユーザー限定
  • プロジェクト単位で「ゲストユーザー」の参加を許可可能
  • ゲストには閲覧・コメントなど限定的な権限のみ
  • 招待リンクやメール経由での参加

モデルC:どちらもゲストとして参加可能

例:Google Drive(共有設定による)、Airtable

  • ワークスペースごとゲストユーザーを許可できる
  • 管理が複雑になりやすいが、柔軟性が高い
  • 共有ポリシーで制御

おすすめ:モデルBを基本とする

  • 外部コラボはプロジェクト単位に限定
  • ワークスペースには原則、組織内メンバーのみ
  • project_members.external = true などで外部ユーザーを明示
  • ゲストのアクセス権限を role_idpolicy で制限

Q4. アクセス制御はどう設計すべきか?(RBAC, ABAC, PBAC)

モデルA:RBAC(ロールベースアクセス制御)
例:Slack、Notion、GitHub
admin / editor / viewer / guest のようなロールに応じてアクセスを制御する。
実装がシンプルでUIにもわかりやすいが、細かい条件に対応しづらい。

モデルB:ABAC(属性ベースアクセス制御)
例:Google Drive、Microsoft Azure
ユーザーやリソースの属性(例:部署やタグ)に基づいて制御する。
柔軟だが、設計や運用が複雑で、権限が見えにくくなりやすい。

モデルC:PBAC(ポリシーベースアクセス制御)
例:AWS IAM、Google Cloud IAM
「誰が」「どのリソースに」「何ができるか」のルール(ポリシー)を定義して管理する。
RBACやABACを含む強力なモデルだが、初期から導入するには重い。

おすすめ:RBACを基本にし、PBACに発展できる設計にしておく
まずは role_id をメンバーシップに持たせてRBACで始める。
roles テーブルと permissions テーブルを切り分けておけば、将来的に柔軟なポリシー設計にも対応しやすい。

Q5. どのようなリソースと permission を定義すべきか?

リソースは、アプリケーション上の「操作対象」や「管理対象」の単位。
permission は、「誰が」「どのリソースに」「どの操作をできるか」を定義する。

モデルA:永続データをリソースとする
例:organization, workspace, project, document など
構造化されたデータを管理する場合に適しており、リソースごとに CRUD 操作を定義しやすい。

モデルB:一時的または生成系のリソース
例:summary, comment, task, notification など
ユーザー操作やAIなどにより動的に生成されるが、場合によっては閲覧や編集制御が必要になる。

モデルC:機能・操作単位をリソースと見なす
例:invitation.send, export.download, integration.connect など
個別の機能やワークフローに対してアクセスを制限したい場合に使う。

おすすめ:モデルAをベースに、必要に応じてB・Cを追加
データ構造として明確なもの(project, documentなど)をリソースとし、
特殊な操作(共有、生成、接続など)は必要に応じて別リソースとして定義する。

よく使われる permission の例:

  • organization.view, organization.manage
  • workspace.create, workspace.invite, workspace.delete
  • project.create, project.edit, project.archive
  • document.read, document.comment, document.delete
  • invitation.send, integration.connect, export.download

Q6. 誰にどう permission を割り当てるべきか?(role・policy設計)

permission は定義しただけでは意味がなく、誰にどう割り当てるか(=ポリシー)が必要になる。

モデルA:roleベースで割り当てる(RBAC)
例:admin / editor / viewer / guest
事前に定義したロールに対して一括で permission を割り当てる。
UIにも反映しやすく、ユーザー管理がシンプル。

モデルB:個別のユーザーに直接 permission を付与(user-permission mapping)
特定の例外ケースに対応できるが、管理が煩雑になりやすい。
規模が大きくなるとポリシースプロール(権限の乱立)を招きやすい。

モデルC:role + context(スコープ)ベースの柔軟なポリシー設計
例:projectのadminと、workspace全体のviewerを両立する
ロールは維持しつつ、スコープごとに割り当てを変える。現代的なSaaSに多い。

おすすめ:roleベースを基本とし、必要に応じてスコープや属性で分岐できる仕組みにしておく

  • まずは role → permission の構成でスタート
  • 将来、project単位や一部例外に対応したくなったら policy テーブルを追加
  • 個別permissionの付与は避ける(例外的に限定)

おすすめで作った場合のER図

erDiagram
  %% 所属関係
  users ||--o{ org_members : belongs_to
  organizations ||--o{ org_members : has
  organizations ||--o{ workspaces : has
  workspaces ||--o{ workspace_members : has
  users ||--o{ workspace_members : belongs_to
  workspaces ||--o{ projects : has
  projects ||--o{ project_members : has
  users ||--o{ project_members : belongs_to

  %% 権限まわり
  project_members }o--|| roles : has_project_role
  workspace_members }o--|| roles : has_workspace_role
  roles ||--o{ role_permissions : defines
  permissions ||--o{ role_permissions : included_in

  %% リソース
  projects ||--o{ artifacts : has
  projects ||--o{ invitations : has
  projects ||--o{ summaries : has

  %% Billing
  organizations ||--o{ billing_accounts : has
  billing_accounts ||--o{ subscriptions : has
  workspaces ||--o{ usage_logs : has
  users ||--o{ usage_logs : has

  %% テーブル定義
  users {
    uuid id PK
    string email
    string name
  }

  organizations {
    uuid id PK
    string name
    string org_type
    string primary_domain
  }

  org_members {
    uuid organization_id FK
    uuid user_id FK
    string role
  }

  workspaces {
    uuid id PK
    uuid organization_id FK
    string name
  }

  workspace_members {
    uuid workspace_id FK
    uuid user_id FK
    uuid role_id FK
  }

  projects {
    uuid id PK
    uuid workspace_id FK
    string name
    string kind
  }

  project_members {
    uuid project_id FK
    uuid user_id FK
    uuid role_id FK
    boolean external
  }

  roles {
    uuid id PK
    string name
    string scope
  }

  permissions {
    uuid id PK
    string resource
    string action
  }

  role_permissions {
    uuid role_id FK
    uuid permission_id FK
  }

  artifacts {
    uuid id PK
    uuid project_id FK
    string type
    string visibility
    uuid owner_id FK
  }

  invitations {
    uuid id PK
    uuid project_id FK
    string email
    string token
    timestamp expires_at
  }

  summaries {
    uuid id PK
    uuid project_id FK
    string content
    timestamp generated_at
  }

  billing_accounts {
    uuid id PK
    uuid organization_id FK
    string billing_email
    string billing_method
  }

  subscriptions {
    uuid id PK
    uuid billing_account_id FK
    string plan
    int seat_count
    timestamp started_at
    timestamp ended_at
  }

  usage_logs {
    uuid id PK
    uuid workspace_id FK
    uuid user_id FK
    string metric
    float amount
    timestamp occurred_at
  }

関連記事

カテゴリー

アーカイブ

Lang »