EXERCISE 60分

ストーリー

佐藤CTO
Step 2で学んだアーキテクチャ設計の各要素を統合し、NexPayの設計ドキュメントを完成させよう
佐藤CTO
このドキュメントは、開発チーム全員が参照する設計の拠り所になる。曖昧な部分が残っていれば、実装時に混乱が生じる。明確に、具体的に記述してほしい

ミッション概要

ミッションテーマ目安時間
Mission 1C4 Container Diagramの詳細化15分
Mission 2サービス間通信フローの設計15分
Mission 3データモデルの設計15分
Mission 4インフラ構成の最適化15分

Mission 1: C4 Container Diagramの詳細化(15分)

要件

Step 2-1, 2-2で学んだ内容を基に、C4 Level 2のContainer Diagramを詳細化してください。

  1. 各コンテナ(サービス)の技術スタックを明記
  2. コンテナ間の通信プロトコルを明記
  3. 外部システムとの接続点を明記
解答例
graph TD
    subgraph Clients["クライアント"]
        MA["Mobile App<br/>Flutter"]
        MD["Merchant Dashboard<br/>Next.js"]
    end

    GW["API Gateway<br/>Kong + Envoy<br/>認証・レート制限・ルーティング"]

    subgraph Services["マイクロサービス(Kotlin / Spring Boot)"]
        PAY["Payment Service<br/>DB: Aurora PostgreSQL (CDE)"]
        ACC["Account Service<br/>DB: Aurora PostgreSQL<br/>Cache: ElastiCache Redis"]
        TRF["Transfer Service<br/>DB: Aurora PostgreSQL"]
        INV["Investment Service<br/>DB: Aurora PostgreSQL + DynamoDB"]
        KYC["KYC Service<br/>DB: DynamoDB<br/>Storage: S3"]
        NTF["Notification Service<br/>DB: DynamoDB"]
    end

    EB["Event Bus<br/>Amazon MSK (Kafka)"]

    subgraph External["外部システム"]
        CN["Card Network<br/>ISO 8583"]
        BK["Bank API<br/>全銀プロトコル"]
        EX["Exchange API<br/>REST/FIX"]
        PUSH["FCM / APNs"]
        SES["SES"]
    end

    MA -->|"HTTPS/REST"| GW
    MD -->|"HTTPS/REST"| GW
    GW -->|"gRPC"| PAY
    GW -->|"gRPC"| ACC
    GW -->|"gRPC"| TRF
    GW -->|"gRPC"| INV

    PAY -->|"gRPC"| ACC
    PAY --> CN
    PAY --> EB

    ACC -->|"gRPC"| KYC
    ACC --> EB

    TRF -->|"gRPC"| ACC
    TRF --> BK
    TRF --> EB

    INV -->|"gRPC"| ACC
    INV --> EX
    INV --> EB

    EB --> NTF
    NTF --> PUSH
    NTF --> SES

    style GW fill:#f3e5f5,stroke:#6a1b9a,stroke-width:2px
    style EB fill:#fff3e0,stroke:#e65100,stroke-width:2px
    style PAY fill:#ffebee,stroke:#c62828
    style ACC fill:#e3f2fd,stroke:#1565c0

Mission 2: サービス間通信フローの設計(15分)

要件

以下の3つのユースケースについて、サービス間の通信フローをシーケンス図形式で記述してください。

  1. QRコード決済(同期フロー)
  2. お釣り投資(非同期フロー)
  3. 銀行送金(Sagaフロー)
解答例

1. QRコード決済(同期フロー):

sequenceDiagram
    participant U as User
    participant GW as API GW
    participant Pay as Payment
    participant Acc as Account
    participant CN as CardNet
    participant K as Kafka

    U->>GW: リクエスト
    GW->>Pay: リクエスト
    Pay->>Acc: 残高確認 (gRPC)
    Acc-->>Pay: 残高OK
    Pay->>CN: 与信承認 (ISO 8583)
    CN-->>Pay: 承認OK
    Pay->>Acc: 残高引落 (gRPC)
    Acc-->>Pay: 引落完了
    Pay->>K: PaymentCompleted (非同期)
    Pay-->>GW: 決済完了レスポンス
    GW-->>U: 決済完了

    Note over K: 非同期後続処理
    K->>K: Notification: 決済通知送信
    K->>K: Settlement: 精算データ蓄積
    K->>K: Point: ポイント付与

合計レイテンシ: p99 < 800ms(同期部分のみ)

2. お釣り投資(非同期フロー):

sequenceDiagram
    participant Pay as Payment
    participant K as Kafka
    participant CI as ChangeInvestment
    participant Acc as Account
    participant Inv as Investment
    participant Ntf as Notification

    Pay->>K: PaymentCompleted
    K->>CI: お釣り計算
    Note over CI: 例: 500円の決済<br/>1000 - 500 = 500円のお釣り
    CI->>Acc: お釣り分を投資口座に振替 (gRPC)
    CI->>Inv: 投資信託の購入注文
    Inv->>K: InvestmentOrderPlaced
    K->>Ntf: 「お釣り投資500円を実行しました」通知

3. 銀行送金(Sagaフロー):

graph TD
    START["Saga Orchestrator"]
    S1["Step 1: KYC Service<br/>本人確認状態チェック"]
    S1OK{{"成功?"}}
    S1NG["送金拒否<br/>理由通知"]
    S2["Step 2: Account Service<br/>送金元残高確認・仮引落"]
    S2OK{{"成功?"}}
    S2NG["送金拒否<br/>残高不足通知"]
    S3["Step 3: Transfer Service<br/>銀行API送金実行"]
    S3OK{{"成功?"}}
    S3NG["補償TX<br/>Account: 仮引落の戻し"]
    S4["Step 4: Notification Service<br/>送金完了通知"]
    S4OK{{"成功?"}}
    S4NG["ログ記録<br/>(通知失敗は送金失敗にしない)"]
    DONE["完了"]

    START --> S1 --> S1OK
    S1OK -->|"成功"| S2
    S1OK -->|"失敗"| S1NG
    S2 --> S2OK
    S2OK -->|"成功"| S3
    S2OK -->|"失敗"| S2NG
    S3 --> S3OK
    S3OK -->|"成功"| S4
    S3OK -->|"失敗"| S3NG
    S4 --> S4OK
    S4OK -->|"成功"| DONE
    S4OK -->|"失敗"| S4NG

    style DONE fill:#e8f5e9,stroke:#2e7d32,stroke-width:2px
    style S1NG fill:#ffebee,stroke:#c62828
    style S2NG fill:#ffebee,stroke:#c62828
    style S3NG fill:#ffebee,stroke:#c62828
    style S4NG fill:#fff3e0,stroke:#e65100

Mission 3: データモデルの設計(15分)

要件

Payment ServiceとAccount Serviceの主要なデータモデルを設計してください。

  1. Payment Serviceのイベントソーシング用スキーマ
  2. Account Serviceの残高管理テーブル
  3. 決済の読み取りモデル(CQRS)
解答例
-- 1. Payment Service: イベントストア
CREATE TABLE payment_events (
    event_id        UUID PRIMARY KEY,
    payment_id      UUID NOT NULL,
    event_type      VARCHAR(50) NOT NULL,
    event_data      JSONB NOT NULL,
    version         INTEGER NOT NULL,
    occurred_at     TIMESTAMPTZ NOT NULL,
    UNIQUE (payment_id, version)
) PARTITION BY RANGE (occurred_at);

-- 2. Account Service: 残高管理
CREATE TABLE accounts (
    account_id      UUID PRIMARY KEY,
    user_id         UUID NOT NULL UNIQUE,
    balance         BIGINT NOT NULL DEFAULT 0,   -- 円単位(整数)
    pending_amount  BIGINT NOT NULL DEFAULT 0,
    currency        VARCHAR(3) NOT NULL DEFAULT 'JPY',
    status          VARCHAR(20) NOT NULL,
    version         INTEGER NOT NULL DEFAULT 0,  -- 楽観的ロック
    updated_at      TIMESTAMPTZ NOT NULL,
    CHECK (balance >= 0),
    CHECK (pending_amount >= 0)
);

-- 残高変更履歴(監査用)
CREATE TABLE balance_transactions (
    tx_id           UUID PRIMARY KEY,
    account_id      UUID NOT NULL REFERENCES accounts(account_id),
    tx_type         VARCHAR(30) NOT NULL,  -- PAYMENT, TRANSFER, INVESTMENT, etc.
    amount          BIGINT NOT NULL,
    balance_before  BIGINT NOT NULL,
    balance_after   BIGINT NOT NULL,
    reference_id    UUID NOT NULL,         -- 決済ID/送金ID等
    idempotency_key VARCHAR(100) UNIQUE,
    created_at      TIMESTAMPTZ NOT NULL
);

-- 3. 決済の読み取りモデル(CQRS)
-- DynamoDB / ElastiCache向け
-- {
--   "paymentId": "uuid",
--   "merchantId": "uuid",
--   "merchantName": "コンビニA 渋谷店",
--   "amount": 500,
--   "currency": "JPY",
--   "status": "CAPTURED",
--   "paymentMethod": "QR_CODE",
--   "pointsEarned": 5,
--   "createdAt": "2026-02-14T12:00:00Z",
--   "capturedAt": "2026-02-14T12:00:01Z"
-- }

設計のポイント:

  • 残高はBIGINT(整数)で管理。浮動小数点は金融で使用不可
  • 楽観的ロック(versionカラム)で並行更新を制御
  • CHECK制約でマイナス残高を防止
  • 冪等性キーで二重処理を防止

Mission 4: インフラ構成の最適化(15分)

要件

Step 2-4のコスト概算(月額2,850万円、年間3.4億円)を予算3億円以内に最適化してください。

  1. コスト削減の施策を3つ以上提案
  2. 各施策の削減額とトレードオフを明記
  3. 最適化後のコスト概算を算出
解答例
施策削減額(月)トレードオフ
EC2 RI 3年契約(東京)-200万円3年間のコミットメント
大阪リージョンをWarm Standby化(常時50%→障害時100%)-150万円フェイルオーバー時間が5分→15分に延長
Savings Plans適用(コンピューティング全体)-100万円1年間のコミットメント
MSKをt3.smallインスタンスに縮小(初期)-50万円将来のスケールアウト時に再設計
CloudWatch → Grafana Cloud移行-30万円ベンダーロックイン軽減

最適化後:

  • 月額: 2,850 - 530 = 2,320万円
  • 年間: 約2.78億円
  • 予算3億円以内に収まる(余裕: 約2,200万円)

CFOへの説明: 「3年RI契約とSavings Plansにより年間3,600万円のコスト削減を実現します。大阪リージョンのWarm Standby化により決済以外のサービスのRTOが15分に延長しますが、決済基盤の5分RTOは維持します。この構成で年間予算3億円以内に収まります」


達成度チェック

ミッションテーマ完了
Mission 1C4 Container Diagramの詳細化
Mission 2サービス間通信フローの設計
Mission 3データモデルの設計
Mission 4インフラ構成の最適化

まとめ

ポイント内容
Container Diagram技術スタック・通信プロトコルを含む詳細な設計図
通信フロー同期/非同期/Sagaのハイブリッド設計
データモデルイベントソーシング + CQRS + 冪等性の統合設計
コスト最適化トレードオフを明示した上での予算内への最適化

チェックリスト

  • C4 Container Diagramを技術スタック付きで完成させた
  • 3つのユースケースの通信フローを設計できた
  • イベントソーシング/CQRS対応のデータモデルを設計できた
  • コスト最適化施策を提案し、予算内に収めた

次のステップへ

次はStep 2の理解度チェッククイズです。アーキテクチャ設計の理解度を確認しましょう。


推定読了時間: 60分