microservices-decomposition について
アーキテクトや開発チーム向けに、マイクロサービス分割設計を作成します。ドメイン駆動設計の境界づけられたコンテキストを基にサービス境界を定め、通信方式、データ所有権、移行計画、チームの担当も扱います。
主な機能
- 01ドメインと境界づけられたコンテキストの分析
- 02サービス境界と責務の定義
- 03同期・非同期の通信方式の選定
- 04データ所有権と移行方式の整理
- 05段階的な移行とチーム担当の計画
活用シーン
- 01モノリスの段階的な分割計画
- 02新規システムのサービス境界設計
- 03サービス依存関係、データ所有権、チーム責務の調整
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ mohitagw15856/ pm-claude-skills --skill microservices-decompositionインストール後、Claude Code で/microservices-decompositionを入力して読み込まれたか確認します。
詳細
マイクロサービス分割
システムの完全なマイクロサービス分割設計を作成します。既存のモノリスを分割する場合も、新しいシステムのサービス境界を設計する場合も対象です。ドメイン駆動設計(DDD)の概念に基づき、まず境界づけられたコンテキストを特定し、そこからサービス境界を導き出してください。通信パターンの判断(同期と非同期、イベントと RPC)、データ所有権のルール、モノリスを分割する場合の現実的な移行計画を含めます。コンウェイの法則は現実です。組織との整合性に関するセクションも含めてください。成果物は抽象的なアーキテクチャ図ではなく、チームが実装を開始できるだけの具体性を備えている必要があります。
必要な入力
すでに提供されていない場合は、次の情報を尋ねてください。
- システムまたはドメインの説明 — システムの役割、中核となるドメイン、対応する主要なビジネスプロセス
- 現在のアーキテクチャ — モノリス(技術スタックと大まかなモジュール構成を説明)、部分的なサービス(既存サービスを列挙)、またはグリーンフィールド
- チーム構成 — チーム数、分かっていればチーム名、おおよそのチーム規模。これがサービスの所有権を決める要素になります
- パフォーマンスとスケーラビリティの要件 — ドメイン領域ごとの具体的な SLA、負荷特性、スケーリング上の制約
- 移行上の制約 — 一度に書き換えられないもの、厳しい期限、ダウンタイムゼロの要件、予算上の制約
- 統合ポイント — 外部システム、サードパーティ API、変更できないレガシーシステム
モノリスを分割する場合は、さらに次の情報も尋ねてください。コードベースのおおよその規模、現在もっとも変更が難しい箇所、チームが結合による摩擦をもっとも強く感じている箇所。
出力形式
マイクロサービス分割:[システム名]
作成者: [名前/チーム] 日付: [日付] アーキテクチャの種類: [モノリスの分割/新規システムの設計] 現在の状態: [現在の状態を一文で説明] 目標の状態: [望ましい最終状態を一文で説明]
1. ドメイン分析
コアドメイン
[1段落:このシステムのコアドメインは何ですか。ビジネスの根本的な役割は何ですか。競争上の差別化につながる要素は何ですか。コアドメインにはもっとも多くの投資を行い、もっとも明確なサービス境界を設けます。]
ドメインマップ
サービス境界を割り当てる前に、重要なサブドメインをすべて列挙してください。各サブドメインを分類します。
| サブドメイン | 種類 | 説明 | モノリス内の現在の場所 |
|---|---|---|---|
| [サブドメイン、例:注文管理] | コア | [役割と重要な理由] | [モジュール/パッケージ名または「新規」] |
| [サブドメイン、例:在庫] | コア | [説明] | [場所] |
| [サブドメイン、例:通知] | 支援 | [説明] | [場所] |
| [サブドメイン、例:請求] | 支援 | [説明] | [場所] |
| [サブドメイン、例:レポート] | 汎用 | [説明 — 既製ソリューションの候補] | [場所] |
| [サブドメイン、例:ユーザー認証] | 汎用 | [説明] | [場所] |
サブドメインの種類: コア=競争上の差別化につながるため、慎重に構築します。支援=必要ですが差別化にはつながらないため、実用性を重視して構築します。汎用=コモディティのため、購入するかオープンソースを利用します。
2. 境界づけられたコンテキストマップ(ASCII)
┌─────────────────────────────────────────────────────────────────┐
│ [System Name] │
│ │
│ ┌──────────────────┐ ┌──────────────────┐ │
│ │ [Context A] │ │ [Context B] │ │
│ │ │─ ─►│ │ │
│ │ [key concepts] │ │ [key concepts] │ │
│ └──────────────────┘ └──────────────────┘ │
│ │ │ │
│ │ event │ sync │
│ ▼ ▼ │
│ ┌──────────────────┐ ┌──────────────────┐ │
│ │ [Context C] │ │ [Context D] │ │
│ │ │ │ │ │
│ │ [key concepts] │ │ [key concepts] │ │
│ └──────────────────┘ └──────────────────┘ │
│ │ │
│ ┌────────┘ │
│ ▼ │
│ ┌──────────────────┐ │
│ │ [Context E] │ │
│ │ [key concepts] │ │
│ └──────────────────┘ │
│ │
│ External: [Third-party system] ──► [Context that owns it] │
└─────────────────────────────────────────────────────────────────┘
Legend: ──► sync call - -► async event ═══ shared kernel
ドメイン分析から導き出した実際の境界づけられたコンテキストを使って、このマップを作成してください。頻繁に通信するコンテキストは、近くに配置します。矢印には関係の種類を記載してください。
コンテキスト間の関係
| 上流コンテキスト | 下流コンテキスト | 関係の種類 | 統合パターン |
|---|---|---|---|
| [コンテキスト A] | [コンテキスト B] | 顧客・供給者 | REST API 呼び出し |
| [コンテキスト B] | [コンテキスト C] | 公開された言語 | メッセージバス経由のドメインイベント |
| [コンテキスト X] | [コンテキスト Y] | 追従者 | [下流側が上流側のモデルに準拠] |
| [コンテキスト X] | [コンテキスト Y] | 腐敗防止層 | [ACL が上流側のモデルをローカルモデルに変換] |
3. 提案するサービス一覧
| サービス名 | 境界づけられたコンテキスト | 主な責任 | 担当チーム | 技術スタック | 優先度 |
|---|---|---|---|---|---|
| [service-name] | [コンテキスト] | [1文で、このサービスが担当することと実行することを記載] | [チーム] | [言語/フレームワーク] | [P1/P2/P3] |
| [service-name] | [コンテキスト] | [責任] | [チーム] | [スタック] | [優先度] |
| [service-name] | [コンテキスト] | [責任] | [チーム] | [スタック] | [優先度] |
| [service-name] | [コンテキスト] | [責任] | [チーム] | [スタック] | [優先度] |
| [service-name] | [コンテキスト] | [責任] | [チーム] | [スタック] | [優先度] |
サービス数: [提案するサービス数N]、[境界づけられたコンテキスト数M]。複数のサービスに対応するコンテキストがある場合は、その理由を記載してください。たとえば、「Orders コンテキストは、拡張性の要件が異なるため、order-intake と order-fulfillment に分割します。」
サービス責任のルール(上記のすべてのサービスに適用)
- 単一の境界づけられたコンテキストを所有すること — 1つのサービスが2つの境界づけられたコンテキストにまたがることはありません
- 独自のデータを所有すること — 他のサービスがデータベースに直接アクセスすることはありません
- 独立してデプロイ可能であること — 他のサービスと連携したデプロイは不要です
- 担当チームが明確に定義されていること — 複数のチームが1つのサービスを共同で所有することはありません
- 定義済みの API コントラクトを公開すること — 内部実装ではありません
4. サービス間通信パターン
パターンの判断マトリックス
| 通信のニーズ | 推奨パターン | 理由 |
|---|---|---|
| 別のサービスの現在の状態を照会する | 同期 REST / gRPC | 低レイテンシが必要であり、呼び出し元は即時の応答を必要とします |
| 状態変更を他のサービスに通知する | 非同期ドメインイベント | サービス間の依存を減らし、複数のコンシューマーに対応します。送信側は処理されるタイミングを問いません |
| 複数のサービスにまたがる長時間実行ワークフロー | 非同期サガ(コレオグラフィまたはオーケストレーション) | ワークフロー全体を所有する単一のサービスがなく、各ステップが失敗した場合にはロールバックが必要です |
| 読み取り頻度の高いサービス間集約 | CQRS 読み取りモデル / マテリアライズドビュー | 読み取り時の頻繁な同期呼び出しを避け、用途に適した読み取りモデルを構築します |
| クライアントへのリアルタイムプッシュ | WebSocket ゲートウェイサービス | 接続管理を一元化します。サービスがイベントを発行し、ゲートウェイがプッシュします |
サービスごとの通信判断
| サービス | 呼び出し先(同期) | 発行するイベント | 購読するイベント |
|---|---|---|---|
| [service-name] | [service-name(エンドポイント)] | [EventName] | [EventName] |
| [service-name] | — | [EventName], [EventName] | [EventName] |
| [service-name] | [service-name(エンドポイント)] | — | [EventName] |
イベントカタログ
| イベント名 | プロデューサー | コンシューマー | ペイロード(主なフィールド) | トリガー |
|---|---|---|---|---|
| [OrderPlaced] | [order-service] | [inventory-service, notification-service] | orderId, customerId, lineItems, totalAmount | 顧客が注文を送信 |
| [InventoryReserved] | [inventory-service] | [order-service] | orderId, reservationId, items | 在庫の引き当てが成功 |
| [PaymentProcessed] | [payment-service] | [order-service, notification-service] | orderId, paymentId, amount, status | 支払いが確定 |
5. データ所有権マトリックス
各データは、ちょうど1つのサービスが所有します。他のサービスが読み取りモデルをキャッシュまたは投影することはできますが、所有元のデータベースには書き込みません。
| データエンティティ | 所有サービス | 正式なデータストア | 利用サービス | アクセスパターン |
|---|---|---|---|---|
| [Order] | [order-service] | [PostgreSQL] | [fulfillment-service, reporting-service] | イベントサブスクリプション+読み取り API |
| [Customer] | [customer-service] | [PostgreSQL] | [order-service, notification-service] | 同期 API 呼び出し |
| [Product Catalog] | [catalog-service] | [PostgreSQL] | [order-service, inventory-service] | 同期 API+ローカルにキャッシュしたコピー |
| [Inventory Level] | [inventory-service] | [Redis + PostgreSQL] | [catalog-service (read only)] | イベントサブスクリプション |
| [Payment Record] | [payment-service] | [PostgreSQL] | [order-service] | イベントサブスクリプション |
データ移行(モノリスを分解する場合)
| データエンティティ | 現在の場所 | 移行先サービス | 移行方法 | データ量 | リスク |
|---|---|---|---|---|---|
| [Entity] | [monolith.orders table] | [order-service] | デュアルライト後に切り替え | [X rows] | [High/Med/Low] |
| [Entity] | [monolith.users table] | [customer-service] | 抽出し、CDC 経由で同期 | [X rows] | [High/Med/Low] |
6. API 契約の定義
各サービスの公開範囲を定義します。完全な OpenAPI 仕様は別途作成し、このセクションでは契約の境界を定めます。
[service-name] API
ベースパス: /api/v1/[resource]
担当チーム: [Team]
SLA: [p99 latency target, availability target]
| エンドポイント | メソッド | 説明 | 認証必須 | レート制限 |
|---|---|---|---|---|
/[resources] | GET | ページネーション付きで[resources]を一覧表示 | はい | [X req/min] |
/[resources]/{id} | GET | ID で単一の[resource]を取得 | はい | [X req/min] |
/[resources] | POST | 新しい[resource]を作成 | はい | [X req/min] |
/[resources]/{id} | PUT | [resource]を更新 | はい | [X req/min] |
/[resources]/{id} | DELETE | [resource]を論理削除 | はい — 権限昇格が必要 | [X req/min] |
[各サービスについて繰り返します。]
7. ストラングラーフィグ移行計画(モノリスを分解する場合)
ストラングラーフィグパターンを使用します。サービスを段階的に抽出し、ファサード経由でトラフィックをルーティングして、モノリスのモジュールを1つずつ廃止します。
移行フェーズ
Phase 1: Foundation (Weeks 1–[N])
- Deploy service infrastructure (CI/CD, observability, service mesh)
- Extract lowest-risk, highest-value service first
- Monolith continues to serve all traffic
Phase 2: First Extractions (Weeks [N]–[M])
- Extract P1 services
- API gateway routes selected traffic to new services
- Monolith handles remaining traffic via facade pattern
- Both paths write to shared DB during transition (dual-write)
Phase 3: Core Domain Services (Weeks [M]–[P])
- Extract P1 core domain services
- Data migration for extracted services
- Remove dual-write paths for completed migrations
Phase 4: Monolith Retirement (Weeks [P]–[Q])
- Extract remaining services
- Monolith serves no production traffic
- Decommission monolith infrastructure
フェーズ別ロードマップ
| フェーズ | 抽出するサービス | 移行方法 | チーム | 期間 | 依存関係 | 成功基準 |
|---|---|---|---|---|---|---|
| 1 | [service-name] | [Strangler facade / Branch by abstraction / Event interception] | [Team] | [X weeks] | [Infra ready, CI/CD pipeline] | [新しいサービスへのトラフィック移行完了、2週間エラーゼロ] |
| 2 | [service-name] | [Approach] | [Team] | [X weeks] | [Phase 1 complete] | [Success metric] |
| 3 | [service-name] | [Approach] | [Team] | [X weeks] | [Phase 2 complete] | [Success metric] |
ロールバック計画
各移行フェーズについて、ロールバックのトリガーと手段を定義します。
- ロールバックのトリガー: 新しいサービスのエラー率が [X%] を超えた状態が [Y minutes] 続く、または p99 レイテンシが [threshold] を超える
- ロールバックの手段: API ゲートウェイのフィーチャーフラグにより、5分未満で全トラフィックをモノリスのパスに戻す
- データのロールバック: 必要に応じて再実行できるよう、切り替え後 [X weeks] はデュアルライトを維持する
8. 組織との整合性(コンウェイの法則)
コンウェイの法則:システムのアーキテクチャは、それを構築する組織のコミュニケーション構造を反映します。サービスのオーナーシップをチームの境界に合わせて設計するか、チームの境界を変更してください。
| サービス | オーナーとして提案するチーム | 現在のチーム割り当て | 必要な変更 |
|---|---|---|---|
| [service-name] | [Team A] | [同じ/異なる] | [変更なし/Team A に移管/新しいチームが必要] |
| [service-name] | [Team B] | [現在は Team A] | [オーナーシップを移管] |
特定された不整合:
- [不整合 1:例:「現在、通知サービスは 2 つのチームにまたがっています。すでにメッセージング領域を担当している Team B に一元的に割り当ててください。」]
- [不整合 2:例:「レポートサービスは Data Eng が所有していますが、利用者は Product チームです。明確な API 契約と SLA を定めてください。」]
チームトポロジーの推奨事項: [推奨するチーム構成(ストリームアラインドチーム、プラットフォームチーム、イネーブリングチーム)と、それを提案するサービスにどのように対応付けるかを説明してください。]
9. リスク登録簿
| リスク | 発生可能性 | 影響 | 軽減策 | 担当者 |
|---|---|---|---|---|
| 移行中のサービス間のデータ整合性 | 高 | 高 | 突合ジョブを使ったデュアルライト。重要な領域にはイベントソーシングを採用 | [Name] |
| 分散トランザクション(サガ)の複雑さ | 中 | 高 | まずコレオグラフィーから始め、管理が困難になった場合にのみオーケストレーションを追加 | [Name] |
| サービスメッシュの運用オーバーヘッド | 中 | 中 | 最初はメッシュなしで開始し、5 つ以上のサービスをデプロイしてから追加 | [Name] |
| プロセス内呼び出しを置き換えるネットワーク遅延 | 中 | 中 | 積極的にキャッシュし、頻繁な同期呼び出しを避けるように読み取りモデルを設計 | [Name] |
| 移行中のコンウェイの法則に起因する摩擦 | 高 | 中 | 抽出を開始してからではなく、その前にチーム構成を整合させる | [Name] |
| 過剰な分割(ナノサービス化) | 中 | 高 | サービスの最小規模ルールを徹底する。各サービスは、専用チームやデプロイに伴うオーバーヘッドを正当化できる必要がある | [Name] |
| 移行中の可観測性の不足 | 高 | 高 | 最初の抽出の前に分散トレーシングを導入し、相関 ID を設定する | [Name] |
| [コンテキスト固有のリスク] | [レベル] | [レベル] | [軽減策] | [担当者] |
この設計に関する質問:[Slack チャンネルまたは連絡先]
品質チェック
- 境界づけられたコンテキストのマップは、コンテキストを文章で説明するのではなく、関係にラベルを付けた ASCII 図になっている
- インベントリ表の各サービスに、名前が明記された担当チームと、責任を明確に示す一文がある
- データオーナーシップマトリックスでは、すべての主要エンティティを所有サービス 1 つだけに割り当てている。共有オーナーシップはない
- コミュニケーションパターンの決定では、各インタラクションタイプで同期と非同期のどちらを選んだか、その理由を説明している
- モノリスを分解する場合、ストラングラーフィグ移行計画に期間、依存関係、成功基準を含むフェーズがある
- リスク登録簿で、少なくともデータ整合性、分散トランザクション、コンウェイの法則との整合性を扱っている
- 組織との整合性のセクションで、サービスとチームを対応付け、解消すべき不整合を特定している
アンチパターン
- ドメイン分析を完了する前に、サービス境界を定義しないでください。境界づけられたコンテキストのマッピングを行わずに導き出したサービスは、分割すべきものを誤って分割し、結合すべきものを誤って結合します。
- 1 つのサービスの共同オーナーとして、複数のチームを割り当てないでください。共同所有は、所有者がいないのと同じです。各サービスには、その責任を負うチームを必ず 1 つだけ定める必要があります。
- サービス間通信のすべてで、同期 REST 呼び出しをデフォルトにしないでください。非同期イベントでサービスを疎結合にできる場面で同期呼び出しを使うと、連鎖的な障害が発生する可能性があります。
- 明確な理由なく、境界づけられたコンテキストごとに複数のサービスを提案しないでください。過剰な分割(ナノサービス)は、分割によるメリットを上回る運用負荷を生みます。
- 分散トレーシングを導入する前に、移行を始めないでください。可観測性のない状態で移行すると、最初のサービス切り出しによって本番環境でインシデントが発生した際、状況を把握できなくなります。