アプリケーションアーキテクチャ

概要

初心者から実務者向けの包括的解説

アプリケーションアーキテクチャ は、ソフトウェアを「長く・大きく・安全に」育てるための設計技法の体系です。コードが動くかどうかだけでなく、5 年後も保守できるか、10 倍のユーザーに耐えられるか、チームで協働できるか。その土台を決めるのがアーキテクチャです。この章では、現代のアプリケーションアーキテクチャを体系的に整理します。

要点
アプリケーションアーキテクチャは、「どこに何を置き、何を分け、どう育てるか」を決める設計の土台です。単に流行の構成を選ぶのではなく、保守性、変更容易性、拡張性、チーム開発との相性まで含めて考えると全体像がつかみやすくなります。

この章の対象

この章は次の読者を想定しています。

  • 初心者向け: アーキテクチャとは何か、なぜ重要かを知りたい方
  • 中級エンジニア向け: モノリス・マイクロサービス・DDD・Clean Architecture の具体像を掴みたい方
  • テックリード / アーキテクト向け: スケーラビリティ・可用性・選定判断の根拠を深めたい方
  • PM・経営層向け: アーキテクチャ決定が事業にどう影響するか理解したい方

この章で重視すること

  • アーキテクチャを図や用語ではなく、変更に強い構造として理解する
  • モノリスとマイクロサービスを対立ではなく文脈依存の選択として見る
  • API、データ、可観測性、デプロイまで含めて全体設計として捉える
  • ソフトウェア工学 と往復しながら、設計と実装の橋を意識する

2026年のアーキテクチャ潮流

2020 年代後半の実装現場で重要な流れ:

  1. モノリス回帰 — マイクロサービス一辺倒から「適正サイズ」へ回帰(Modular Monolith、Majestic Monolith)
  2. AI 統合前提 — LLM/RAG/ベクトル DB が標準レイヤに
  3. Edge と Serverless の成熟 — Cloudflare Workers、Vercel、Deno Deploy など
  4. プラットフォームエンジニアリング — 内部開発者プラットフォーム(IDP)で組織全体の生産性を上げる
  5. Observability 第一 — OpenTelemetry、eBPF、Distributed Tracing の標準化
  6. 契約駆動開発 — OpenAPI / gRPC / AsyncAPI による API ファースト
  7. Event-Driven とストリーミング — Kafka、EventBridge、NATS、リアルタイム体験
  8. TypeScript / Rust / Go 優勢 — 型安全・速度・所有権の恩恵

目次

  1. アーキテクチャとは何か
  2. なぜアーキテクチャが重要か
  3. アーキテクチャの基本原則
  4. アーキテクチャスタイル全体像
  5. モノリシックアーキテクチャ
  6. 階層化アーキテクチャ
  7. クリーンアーキテクチャとヘキサゴナル
  8. ドメイン駆動設計(DDD)
  9. MVC / MVP / MVVM
  10. マイクロサービスアーキテクチャ
  11. イベント駆動アーキテクチャ
  12. CQRS と Event Sourcing
  13. サーバレスアーキテクチャ
  14. マイクロフロントエンド
  15. API 設計
  16. データアーキテクチャ
  17. キャッシング戦略
  18. メッセージングパターン
  19. スケーラビリティパターン
  20. 可用性パターン
  21. 分散システムパターン
  22. 認証認可アーキテクチャ
  23. オブザーバビリティ
  24. セキュリティアーキテクチャ
  25. テスト戦略
  26. CI/CD とデプロイパターン
  27. 選び方とトレードオフ
  28. 2025-2026 最新動向
  29. まとめ

附録:


アーキテクチャとは何か

初心者向けメモ: アーキテクチャとは「建築」の比喩で、ソフトウェアの大きな構造を決める設計のことです。「どこに何を置くか」「何と何を分けるか」「どう組み合わせるか」を決める行為。コードを書き始める前の土台づくりです。

定義

Martin Fowler の有名な定義:

Architecture is about the important stuff. Whatever that is. (アーキテクチャとは重要なことを扱う。それが何であれ。)

もう少しフォーマルには、IEEE 42010 の定義:

The fundamental concepts or properties of a system in its environment embodied in its elements, relationships, and in the principles of its design and evolution. (システムの要素・関係・設計原則・進化を規定する、環境における基本概念または特性)

つまりアーキテクチャは:

  • 構造:何と何がどう組み合わさるか
  • 関係:コンポーネント間の依存・通信
  • 原則:なぜこの構造を選んだか
  • 進化:将来どう拡張するか

を決めるものです。

コードとアーキテクチャの違い

【図1】抽象化レベル:

graph TD Biz[ビジネス要求] Arch[アーキテクチャ 全体構造] Design[設計 モジュール パターン] Code[コード 実装] Biz --> Arch Arch --> Design Design --> Code
関心事 変更の困難さ
ビジネス要求 何を達成したいか -
アーキテクチャ システム全体の構造 非常に困難(大規模リライト)
設計 モジュール・クラス構造 困難(リファクタ)
コード 具体的な処理 容易(変更・追加)

アーキテクトの仕事

アーキテクトは単に図を描く人ではなく:

  1. 意思決定:トレードオフを評価して選択
  2. 制約の明示:何をやっていい・ダメか
  3. コミュニケーション:開発者・PM・経営層を翻訳
  4. 進化:変化に対応して設計を更新
  5. 教育:チームに設計原則を浸透させる

Fred Brooks の箴言:

「概念的完全性(conceptual integrity)が、システム設計の最も重要な考慮事項である」


なぜアーキテクチャが重要か

初心者向けメモ: 小さな個人プロジェクトではアーキテクチャはあまり重要に見えません。でも人数・コード量・期間が増えるにつれて、その重要性は指数関数的に上がります。「動けばよい」が通用するのは最初だけです。

アーキテクチャ負債の重力

悪いアーキテクチャは 技術的負債 として蓄積します。

【図2】技術的負債の増加カーブ:

graph LR Start[スタート 生産性高] Middle[中盤 生産性が徐々に低下] End[末期 1機能に数週間] Start --> Middle Middle --> End

データベースの 1 カラム追加に数日、簡単な機能追加に数週間、リファクタに数ヶ月 — このような 「変更が高コスト」な状態 が、悪いアーキテクチャが生む最大の損失です。

アーキテクチャが影響する非機能要件

機能要件(何ができるか)と対比される 非機能要件(NFR) の多くがアーキテクチャで決まります。

非機能要件 意味
パフォーマンス 応答速度 99%ile で 200ms 以内
スケーラビリティ 負荷対応力 秒間 10万リクエスト
可用性 稼働率 99.95%(月 22 分停止まで)
信頼性 障害耐性 単一障害で全停止しない
保守性 変更の容易さ 新機能を 1 週間でリリース
テスト容易性 テストの書きやすさ 単体・結合・E2E のバランス
セキュリティ 脅威への耐性 多層防御、最小権限
可観測性 状態の見えやすさ ログ・メトリクス・トレース
コスト効率 経済性 リソース使用最適化
コンプライアンス 法規制順守 GDPR、個人情報保護法

Conway の法則

「システムを設計する組織は、その組織のコミュニケーション構造をそのまま反映した構造のシステムを設計する」 — Melvin Conway, 1967

チーム構成が 3 つなら、自然にシステムも 3 つに分かれる傾向があります。逆に 「望ましいシステム構造に合わせてチームを作る」逆コンウェイ戦略 が、モダンな組織設計の核心です。

アーキテクチャの ROI

  • 良いアーキテクチャ:初期は遅く見えても、長期的に生産性を維持
  • 悪いアーキテクチャ:初期は速く進むが、数年で破綻・書き直し

世界最大級の企業(Netflix、Amazon、Google)は、アーキテクチャに年間数百〜数千人月を投資しています。


アーキテクチャの基本原則

初心者向けメモ: すべてのアーキテクチャスタイルの土台には、数個の基本原則があります。これを押さえれば、新しいパターンに出会っても「なぜそうするのか」が理解しやすくなります。

SOLID 原則

オブジェクト指向設計の 5 原則(Robert C. Martin 提唱)。

原則 意味
S Single Responsibility Principle 単一責任:1 クラスは 1 つの理由で変更される
O Open/Closed Principle 開放/閉鎖:拡張に対して開き、修正に対して閉じる
L Liskov Substitution Principle リスコフ置換:派生クラスは基底クラスと置換可能
I Interface Segregation Principle インターフェース分離:クライアントが使わないメソッドに依存させない
D Dependency Inversion Principle 依存性逆転:抽象に依存し、具象に依存しない

その他の必須原則

  • DRY(Don’t Repeat Yourself):同じ知識を二度書かない
  • KISS(Keep It Simple, Stupid):複雑さは必要悪、シンプルに
  • YAGNI(You Aren’t Gonna Need It):今必要ないものは作らない
  • Separation of Concerns(関心の分離):異なる関心を別モジュールに
  • High Cohesion, Low Coupling(高凝集・低結合):モジュール内はまとまり、モジュール間は疎に
  • Principle of Least Astonishment(驚き最小):予測どおりに動くように設計
  • Composition over Inheritance(継承より合成):is-a より has-a
  • Fail Fast(早く失敗):問題は早期に発覚させる
  • Idempotency(冪等性):同じ操作を何度実行しても結果が変わらない

アーキテクチャの二大テンション

ほとんどのアーキテクチャ判断は、以下の 2 つの軸上のトレードオフです。

【図3】アーキテクチャの基本トレードオフ:

graph LR Simple[シンプル モノリス] Complex[複雑 マイクロサービス 分散] Tight[密結合 高速 内部呼び出し] Loose[疎結合 スケール 独立デプロイ] Simple -.-> Complex Tight -.-> Loose
  • シンプル ⇔ 複雑:複雑さはスケーラビリティや柔軟性と引き換え
  • 密結合 ⇔ 疎結合:疎結合は独立デプロイ可能だが、ネットワーク越しの遅延

アーキテクチャスタイル全体像

初心者向けメモ: アーキテクチャには多数のスタイルがあります。「どれが一番良い」というものはなく、規模・期限・チーム・事業要件で選びます。以下はよく使われるスタイルの俯瞰図です。

主要スタイルマップ

【図4】アーキテクチャスタイルの関係:

graph TD Mono[モノリス シンプル] Modular[モジュラモノリス 構造化] Layered[階層化アーキテクチャ] Clean[Clean ヘキサゴナル オニオン] DDD[DDD ドメイン駆動] Micro[マイクロサービス] Serverless[サーバレス FaaS] Event[イベント駆動 Event Driven] CQRS[CQRS Event Sourcing] Mono --> Modular Modular --> Clean Clean --> DDD DDD --> Micro Micro --> Serverless Event --> CQRS Micro -.-> Event

規模 × 複雑度による選択

規模 推奨スタイル
小(〜数万ユーザー、2-5 人チーム) モノリス
中(〜数百万ユーザー、10-50 人) モジュラモノリス、Clean Architecture
大(数千万〜、50 人以上) マイクロサービス、イベント駆動
エッジ・大量並列 サーバレス、Edge Functions
複雑なドメイン・規制 DDD + CQRS + Event Sourcing

モノリシックアーキテクチャ

初心者向けメモ: モノリス(一枚岩)は「すべてが 1 つのアプリに入った」構造です。「古い・悪い」と誤解されがちですが、多くのスタートアップや中規模プロダクトで最適解です。マイクロサービスより 10 倍速く作れることがあります。

定義

すべての機能を 単一のコードベース・単一のデプロイ単位 で実装するアーキテクチャ。

【図5】モノリシックアーキテクチャ:

graph TD Client[クライアント] LB[Load Balancer] App1[Monolith App Instance 1] App2[Monolith App Instance 2] App3[Monolith App Instance 3] DB[Database] Client --> LB LB --> App1 LB --> App2 LB --> App3 App1 --> DB App2 --> DB App3 --> DB

種類

1. ビッグボールオブマッド(Big Ball of Mud)

構造のない、スパゲッティ化したモノリス。アンチパターン。避けるべき。

2. モジュラモノリス(Modular Monolith)

1 つのデプロイ単位の中で、明確なモジュール境界 を持つ。最近再評価されている。

flowchart TB M["myapp/"] --> U["user/ ユーザーモジュール"] M --> O["order/ 注文モジュール"] M --> I["inventory/ 在庫モジュール"] M --> P["payment/ 決済モジュール"] M --> S["shared/ 共通ライブラリ"]

3. マジェスティックモノリス(Majestic Monolith)

DHH(Basecamp / Ruby on Rails)が提唱。小規模チームで高速開発できる洗練されたモノリス。

モノリスのメリット

  • 開発速度が速い:1 つのリポジトリ、1 つの言語、1 つのデプロイ
  • デバッグが簡単:全てが同じプロセス、スタックトレース完全
  • トランザクション:単一 DB で ACID 保証
  • 運用が単純:1 つのデプロイパイプライン
  • コストが低い:サーバ台数・運用コスト削減

モノリスの課題

  • スケールの天井:全コードが同じプロセス、水平スケールしかない
  • デプロイが重い:小変更でも全体再デプロイ
  • 技術選択の硬直:言語・フレームワークが固定
  • コードベースが巨大化:数百万行になると複雑

典型例

  • Shopify(Ruby on Rails、数十億ドル事業)
  • Basecamp
  • GitHub(初期〜中期)
  • Stack Overflow(.NET、5 台のサーバで数億 PV)

階層化アーキテクチャ

初心者向けメモ: 階層化(Layered)は最も古典的なアーキテクチャです。プレゼンテーション層、ビジネスロジック層、データアクセス層といった 横方向の層 に分ける構造。初心者にも分かりやすく、多くのフレームワーク(Spring、Laravel、Rails、Django)の標準構造です。

典型的な 3 層アーキテクチャ

【図6】3 層アーキテクチャ:

graph TD UI[Presentation Layer UI コントローラ] BL[Business Logic Layer サービス ドメインルール] DA[Data Access Layer リポジトリ ORM] DB[Database] UI --> BL BL --> DA DA --> DB

各層の責務

  1. プレゼンテーション層:ユーザー入力の受付、レスポンス整形(HTTP ハンドラ、UI)
  2. ビジネスロジック層:業務ルール、ワークフロー(サービスクラス、ドメインモデル)
  3. データアクセス層:永続化、DB 操作(リポジトリ、ORM)

4 層以上の例

Controller → Application Service → Domain → Repository

メリット・デメリット

メリット:

  • 分かりやすい
  • 役割分担が明確
  • テストしやすい

デメリット:

  • 層を貫く変更が多発(1 機能追加で全層を触る)
  • ビジネスロジックがサービス層に集中しがち(Anemic Domain Model)
  • 横断的関心事(ログ、認証)の扱いが面倒

クリーンアーキテクチャとヘキサゴナル

初心者向けメモ: Clean Architecture(Robert C. Martin)、Hexagonal Architecture(Alistair Cockburn)、Onion Architecture(Jeffrey Palermo) — これらは 「同じ思想の別表現」 です。共通するキーワードは「ドメインを外側に依存させない」。難しく見えて本質はシンプルです。

コア思想:依存の方向を逆転する

【図7】クリーンアーキテクチャの依存方向:

graph TD UI[UI Web Mobile CLI] App[Application Layer ユースケース] Domain[Domain Layer エンティティ 業務ルール] Infra[Infrastructure DB API フレームワーク] UI --> App App --> Domain Infra --> App Infra -.-> Domain

重要なのは矢印の向き:

  • UI、Infrastructure → Application → Domain
  • Domain は何にも依存しない(純粋な業務ロジック)
  • Infrastructure は Application のインターフェースを実装する(依存性逆転)

層の説明

flowchart TB I["Infrastructure 外側から実装を差し込む"] --> A["Interface Adapters / UI Controllers"] --> U["Use Cases / Application Services"] --> D["Domain Entities / Business Rules"]

具体例:注文ユースケース

// Domain(純粋、フレームワーク非依存)
class Order {
  constructor(
    public readonly id: OrderId,
    public readonly items: OrderItem[],
    public readonly customer: CustomerId
  ) {}

  public total(): Money {
    return this.items.reduce((sum, i) => sum.add(i.subtotal()), Money.zero());
  }
}

// Application(インターフェース定義)
interface OrderRepository {
  save(order: Order): Promise<void>;
  findById(id: OrderId): Promise<Order | null>;
}

class PlaceOrderUseCase {
  constructor(
    private readonly orderRepo: OrderRepository,
    private readonly paymentGateway: PaymentGateway
  ) {}

  async execute(cmd: PlaceOrderCommand): Promise<OrderId> {
    const order = Order.createFrom(cmd);
    await this.paymentGateway.charge(order.total(), cmd.paymentMethod);
    await this.orderRepo.save(order);
    return order.id;
  }
}

// Infrastructure(インターフェースを実装)
class PostgresOrderRepository implements OrderRepository {
  async save(order: Order): Promise<void> {
    // DB 実装
  }
  // ...
}

ヘキサゴナル(Ports and Adapters)

本質は同じ。「ポート」(インターフェース)と「アダプター」(実装)で内外を区切る。

【図8】ヘキサゴナルアーキテクチャ:

graph LR Web[Web HTTP Adapter] CLI[CLI Adapter] Test[Test Driver] App[Application Core ドメイン ユースケース] DB[DB Adapter PostgreSQL] MQ[MQ Adapter Kafka] API[External API Adapter] Web --> App CLI --> App Test --> App App --> DB App --> MQ App --> API

メリット

  • テストが書きやすい:ドメイン層を単独テスト可
  • 技術変更に強い:DB を PostgreSQL → MongoDB へ切り替え可
  • ドメインが保護される:業務ロジックがフレームワークに汚染されない
  • 複雑なドメインに向く:DDD と相性が良い

デメリット

  • 初期コスト高:小プロジェクトでは過剰
  • コード量が増える:インターフェース、DTO など
  • 学習曲線:チーム全員の理解が必要

ドメイン駆動設計(DDD)

初心者向けメモ: DDD(Domain-Driven Design)は Eric Evans が 2003 年に提唱した、複雑なビジネスドメインを扱うための設計アプローチです。用語の揺れを直し、業務エキスパートと開発者が同じ言葉で話すことから始まります。DDD は万能薬ではなく、複雑なドメインの時こそ威力を発揮します。単純な CRUD には過剰です。

8.1 DDD の哲学と歴史

DDD は単なる設計パターン集ではなく、ソフトウェア開発の哲学 です。核心は以下の 3 つ:

  1. ドメインが最優先:技術ではなく業務の複雑性に焦点
  2. モデルとコードを一致させる:設計書とコードの乖離を排除
  3. 業務エキスパートと協働:ドメイン知識を深めながら開発

歴史

できごと
2003 Eric Evans “Domain-Driven Design”(青本)出版
2013 Vaughn Vernon “Implementing Domain-Driven Design”(赤本)— 実装寄り
2015 Alberto Brandolini “Event Storming” 提唱
2016 Vaughn Vernon “Domain-Driven Design Distilled”(緑本)— 入門
2020 以降 マイクロサービス時代で DDD 再評価、CQRS/ES との融合
2024-2025 “Learning Domain-Driven Design”(Vladik Khononov)が新定番

8.2 DDD が向く場面・向かない場面

向く:

  • 複雑なビジネスルール(金融、保険、ヘルスケア、物流、ERP、EC)
  • 長期運用(5-10 年以上のシステム)
  • 多数のステークホルダーと業務エキスパート
  • チームが大きく、複数のサブドメインに分かれる
  • マイクロサービスを適切に分割したい

向かない:

  • 単純な CRUD アプリ(ブログ、問い合わせフォーム)
  • データ変換中心(ETL パイプライン)
  • 実験的プロトタイプ
  • 小規模・短期プロジェクト

8.3 ユビキタス言語(Ubiquitous Language)

業務エキスパート、PM、開発者、コード、ドキュメントすべてで 同じ用語 を使う。DDD の出発点かつ最重要。

悪い例:

  • コード内:UserModelClientEntityAccountDTO
  • PM の資料:「会員」
  • 営業:「顧客」
  • 契約書:「加入者」

→ 翻訳ミス・認識齟齬が頻発。

良い例:

  • 業務もコードもドキュメントも「Member(会員)」で統一
  • コードに class Member と書く
  • 会議でも「Member が Subscription を Upgrade した」と話す

ユビキタス言語の育て方

  1. 業務エキスパートと会話:用語を記録
  2. 用語集(Glossary)を作る:プロジェクト Wiki に
  3. 曖昧な用語は警告:「請求」vs「回収」vs「支払」の違いを明確化
  4. コードに反映:クラス名・メソッド名を自然言語で
  5. 定期的に更新:ドメイン理解が深まれば進化

8.4 戦略的 DDD(Strategic Design)

DDD の 大局的な部分。どこに投資し、どう分割するかを決める。

8.4.1 ドメインとサブドメイン

一つの事業は複数のサブドメインから成る。例:EC サイト

【図DDD-1】EC のサブドメイン分類:

graph TD EC[EC ビジネス全体] Core[コアドメイン 競争優位の源泉] Support[サポートドメイン 必要だが差別化ではない] Generic[汎用サブドメイン 業界共通] EC --> Core EC --> Support EC --> Generic Core --> C1[推薦エンジン] Core --> C2[価格最適化] Core --> C3[在庫最適化] Support --> S1[注文管理] Support --> S2[顧客管理] Generic --> G1[認証] Generic --> G2[請求] Generic --> G3[メール配信] Generic --> G4[通知]
種類 投資 判断
コアドメイン(Core) 最大投資、最優秀エンジニア 自社実装、DDD 適用
サポートドメイン(Supporting) 中程度 自社実装または外注
汎用サブドメイン(Generic) 最小 SaaS 購入、OSS 利用

経営判断として: 「コアドメインに差別化集中、それ以外は買う」が原則。

8.4.2 境界づけられたコンテキスト(Bounded Context)

同じ言葉でも、文脈で意味が違う という事実を受け入れる設計。

例:「商品(Product)」

  • 販売コンテキスト:価格、割引、在庫数、レビュー
  • 在庫コンテキスト:SKU、倉庫位置、入荷予定、棚番号
  • 配送コンテキスト:サイズ、重量、梱包形態、配送業者
  • 請求コンテキスト:単価、税率、通貨、会計コード

「全部まとめた Product クラス」を作ると破綻する。コンテキストごとに別のモデル を持つ。

【図DDD-2】Bounded Context の分離:

graph TD subgraph SalesCtx[販売コンテキスト] SalesProduct[Product 価格 在庫数 レビュー] end subgraph InvCtx[在庫コンテキスト] InvItem[Item SKU 倉庫位置 入荷予定] end subgraph ShipCtx[配送コンテキスト] ShipPackage[Package サイズ 重量 梱包] end subgraph BillCtx[請求コンテキスト] BillSku[BillableSKU 単価 税率 会計コード] end SalesProduct -.ID のみ共有.-> InvItem SalesProduct -.ID のみ共有.-> ShipPackage SalesProduct -.ID のみ共有.-> BillSku

Bounded Context の境界は、チーム境界・DB 境界・デプロイ境界 と一致させるのが理想(Conway の法則)。

8.4.3 コンテキストマップ(Context Map)

複数の Bounded Context の 関係性を可視化 する図。DDD における「組織図」にあたる。

Context Map の 9 パターン

Eric Evans が定義した、コンテキスト間の関係を表す 9 パターン:

【図DDD-3】Context Map パターン:

graph TD CM[Context Map 9 パターン] CM --> P1[Partnership 対等協力] CM --> P2[Shared Kernel 共有カーネル] CM --> P3[Customer Supplier 上流下流] CM --> P4[Conformist 追従] CM --> P5[Anticorruption Layer 腐敗防止層] CM --> P6[Open Host Service 公開ホスト] CM --> P7[Published Language 公開言語] CM --> P8[Separate Ways 分離] CM --> P9[Big Ball of Mud 混沌]
パターン 意味 典型例
Partnership 2 チームが成功失敗を共有。対等な協力 同じ製品の 2 コンテキスト
Shared Kernel 小さな共有モデルを両方で管理 共通の顧客 ID モデル
Customer-Supplier 上流(Supplier)が下流(Customer)のニーズを考慮 ユーザー管理 ← 注文サービス
Conformist 上流の変更に下流が追従するのみ 外部 SaaS API を使う
Anticorruption Layer (ACL) 外部モデルから自分を守る変換層 レガシー / 外部 API 連携
Open Host Service (OHS) 公開プロトコルでサービス提供 REST / gRPC 公開 API
Published Language (PL) 共通言語で情報交換 JSON Schema、Protobuf
Separate Ways 連携せず完全独立 独立事業部
Big Ball of Mud 混沌。避けたいが現実にはある レガシー内部
ACL(Anticorruption Layer)の重要性

特に注目すべきは ACL。外部システムやレガシーの「汚い」モデルが自分のコアドメインを汚染しないよう、変換層で守る。

// 外部 API からのデータ
interface ExternalCustomerDTO {
  customer_id: string;
  first_name: string;
  last_name: string;
  email_address: string;
  status: string;  // "A" / "I" / "X" (意味不明)
}

// ACL で自分のドメイン用に変換
class CustomerAntiCorruptionLayer {
  toDomain(external: ExternalCustomerDTO): Customer {
    return new Customer(
      new CustomerId(external.customer_id),
      new FullName(external.first_name, external.last_name),
      new Email(external.email_address),
      this.mapStatus(external.status)
    );
  }

  private mapStatus(s: string): CustomerStatus {
    switch (s) {
      case "A": return CustomerStatus.Active;
      case "I": return CustomerStatus.Inactive;
      case "X": return CustomerStatus.Suspended;
      default: throw new Error(`Unknown status: ${s}`);
    }
  }
}

8.5 戦術的 DDD(Tactical Design)

個々のコンテキスト内で使う 実装パターン集

8.5.1 Value Object(値オブジェクト)

識別子ではなく、属性で等価性を判断。不変(immutable)。

特徴:

  • 属性がすべて同じなら「同じもの」
  • 作成後は変更不可
  • 副作用フリー
  • 小さく自己完結

例:金額(Money)

class Money {
  constructor(
    public readonly amount: number,
    public readonly currency: Currency
  ) {
    if (amount < 0) throw new Error("Amount must be non-negative");
    Object.freeze(this);
  }

  add(other: Money): Money {
    if (this.currency !== other.currency) {
      throw new Error("Cannot add different currencies");
    }
    return new Money(this.amount + other.amount, this.currency);
  }

  multiply(factor: number): Money {
    return new Money(this.amount * factor, this.currency);
  }

  equals(other: Money): boolean {
    return this.amount === other.amount && this.currency === other.currency;
  }
}

const price = new Money(1000, Currency.JPY);
const tax = price.multiply(0.1);
const total = price.add(tax);   // 新しい Money が返る、元の price は変わらない

Value Object にすべき候補:

  • 金額、通貨、数量
  • 住所、郵便番号、電話番号
  • メールアドレス、URL
  • 日付範囲、期間
  • 座標、温度、距離
  • ID(OrderIdCustomerId など)

Primitive Obsession(プリミティブ強迫観念)の回避:

// 悪い例:プリミティブ型だらけ
function transferMoney(from: string, to: string, amount: number): void { ... }
// 呼び出し側で順序ミスしても型エラーにならない
transferMoney("123", "456", 1000);
transferMoney(1000, "123", "456");  // ← 違反だがコンパイルエラーにならない

// 良い例:Value Object
function transferMoney(from: AccountId, to: AccountId, amount: Money): void { ... }
transferMoney(new AccountId("123"), new AccountId("456"), new Money(1000, JPY));
// 型で守られる

8.5.2 Entity(エンティティ)

一意の識別子で区別されるオブジェクト。属性が変わっても同じ実体とみなす。

class Order {
  constructor(
    public readonly id: OrderId,           // 識別子
    private status: OrderStatus,
    private items: OrderItem[],
    private customerId: CustomerId
  ) {}

  // ビジネスロジックをクラスメソッドに
  addItem(item: OrderItem): void {
    if (this.status !== OrderStatus.Draft) {
      throw new Error("Cannot modify confirmed order");
    }
    this.items.push(item);
  }

  confirm(): void {
    if (this.items.length === 0) {
      throw new Error("Cannot confirm empty order");
    }
    this.status = OrderStatus.Confirmed;
  }

  total(): Money {
    return this.items.reduce(
      (sum, item) => sum.add(item.subtotal()),
      Money.zero()
    );
  }

  // 識別子で等価判定
  equals(other: Order): boolean {
    return this.id.equals(other.id);
  }
}

重要: Entity はデータだけ持つ貧血モデル(Anemic Domain Model)ではなく、ビジネスロジックを持つ のが DDD 流。

8.5.3 Aggregate(集約)

整合性境界 を持つエンティティ群。1 つの Aggregate Root を通じてのみアクセスされ、トランザクションの単位 となる。

例:Order Aggregate

flowchart TB O["Order (Aggregate Root)"] --> I["OrderItem エンティティ、Order 経由でのみアクセス"] O --> S["ShippingAddress Value Object"] O --> T["Total Value Object"]

【図DDD-4】Aggregate の境界:

graph TD subgraph OrderAggregate[Order Aggregate] Root[Order Aggregate Root] Item1[OrderItem 1] Item2[OrderItem 2] Addr[ShippingAddress VO] end External[外部コード] Customer[Customer Aggregate] External --> Root Root --> Item1 Root --> Item2 Root --> Addr Root -.ID のみ参照.-> Customer
Aggregate の 4 設計ルール(Vaughn Vernon)
  1. 境界内で真の不変条件をモデル化:Aggregate 内のルールを守る責務
  2. 小さな Aggregate を設計:大きすぎるとロック競合・性能劣化
  3. 他の Aggregate は ID で参照:オブジェクト参照で繋がない
  4. 結果整合性で外部を更新:別 Aggregate の変更はドメインイベント経由

悪い例:大きすぎる Aggregate

flowchart TB C["Customer (巨大 Aggregate)"] --> O["All Orders (1000 件) 1 注文追加で全部ロック"] C --> R["All Reviews"] C --> W["All Wishlists"] C --> S["All Subscriptions"]

良い例:小さい Aggregate + ID 参照

flowchart LR C["Customer Aggregate"] --> C1["CustomerId"] C --> C2["Name"] C --> C3["Email"] C --> C4["Address"] O["Order Aggregate"] --> O1["OrderId"] O --> O2["CustomerId ID だけ参照"] O --> O3["OrderItems"] O --> O4["Total"]

8.5.4 Domain Event(ドメインイベント)

ドメインで起きた重要な事実 を表現する不変オブジェクト。過去形で命名する(OrderPlacedPaymentFailed)。

abstract class DomainEvent {
  readonly occurredAt: Date = new Date();
  readonly eventId: string = uuid();
}

class OrderPlaced extends DomainEvent {
  constructor(
    public readonly orderId: OrderId,
    public readonly customerId: CustomerId,
    public readonly total: Money
  ) { super(); }
}

class PaymentFailed extends DomainEvent {
  constructor(
    public readonly orderId: OrderId,
    public readonly reason: string
  ) { super(); }
}

用途:

  • Aggregate 間の疎結合通信:直接呼ばずイベント発行
  • 監査ログ:完全な変更履歴
  • Event Sourcing:状態=イベント列
  • 統合:他のコンテキストへの通知
class Order {
  private events: DomainEvent[] = [];

  place(): void {
    this.status = OrderStatus.Placed;
    this.events.push(new OrderPlaced(this.id, this.customerId, this.total()));
  }

  pullEvents(): DomainEvent[] {
    const e = this.events;
    this.events = [];
    return e;
  }
}

// アプリケーションサービス側
async function placeOrder(cmd: PlaceOrderCommand) {
  const order = await orderRepo.findById(cmd.orderId);
  order.place();
  await orderRepo.save(order);
  // イベント発行(メッセージブローカへ)
  const events = order.pullEvents();
  await eventPublisher.publishAll(events);
}

8.5.5 Repository(リポジトリ)

Aggregate の永続化抽象。ドメイン層がインターフェースを定義し、インフラ層が実装。

// ドメイン層(純粋、DB 非依存)
interface OrderRepository {
  findById(id: OrderId): Promise<Order | null>;
  save(order: Order): Promise<void>;
  delete(id: OrderId): Promise<void>;
}

// インフラ層(実装)
class PostgresOrderRepository implements OrderRepository {
  async findById(id: OrderId): Promise<Order | null> {
    const row = await this.db.query(
      'SELECT * FROM orders WHERE id = $1', [id.value]
    );
    return row ? this.toDomain(row) : null;
  }

  async save(order: Order): Promise<void> {
    // SQL / ORM 実装
  }

  private toDomain(row: any): Order {
    // Row → Order オブジェクト変換
  }
}

重要:

  • リポジトリは Aggregate 単位(各 Aggregate Root ごとに 1 つ)
  • コレクション風のインターフェース(findById, save, remove)
  • 複雑なクエリ用に Specification パターンと組み合わせる

8.5.6 Domain Service(ドメインサービス)

Entity にも Value Object にも属さない ビジネスロジック。複数 Aggregate を跨る処理など。

// 例:銀行振込(FromAccount と ToAccount の両方を扱う)
class TransferService {
  constructor(private accountRepo: AccountRepository) {}

  async transfer(from: AccountId, to: AccountId, amount: Money): Promise<void> {
    const fromAccount = await this.accountRepo.findById(from);
    const toAccount = await this.accountRepo.findById(to);

    if (!fromAccount.canWithdraw(amount)) {
      throw new Error("Insufficient balance");
    }

    fromAccount.withdraw(amount);
    toAccount.deposit(amount);

    await this.accountRepo.save(fromAccount);
    await this.accountRepo.save(toAccount);
  }
}

注意: ドメインサービスに何でも入れると Anemic Domain Model(貧血ドメインモデル)化する。可能な限り Entity / Value Object にロジックを入れるのが原則。

8.5.7 Application Service(アプリケーションサービス)

ユースケースのオーケストレーション。ドメインサービスを組み合わせ、トランザクション境界を定める。

class PlaceOrderUseCase {
  constructor(
    private orderRepo: OrderRepository,
    private customerRepo: CustomerRepository,
    private paymentGateway: PaymentGateway,
    private eventPublisher: EventPublisher
  ) {}

  async execute(cmd: PlaceOrderCommand): Promise<OrderId> {
    // 1. ドメインオブジェクト取得
    const customer = await this.customerRepo.findById(cmd.customerId);
    if (!customer) throw new NotFoundError("Customer not found");

    // 2. Aggregate 作成
    const order = Order.createFrom(cmd, customer);

    // 3. 外部サービス呼び出し
    await this.paymentGateway.charge(order.total(), cmd.paymentMethod);

    // 4. 永続化(ここがトランザクション境界)
    await this.orderRepo.save(order);

    // 5. イベント発行
    await this.eventPublisher.publishAll(order.pullEvents());

    return order.id;
  }
}

8.5.8 Factory(ファクトリ)

複雑な Aggregate の生成を分離。生成ロジックが複雑な場合のみ。

class OrderFactory {
  static createFromCart(cart: ShoppingCart, customer: Customer): Order {
    const items = cart.items.map(ci => new OrderItem(
      ci.productId,
      ci.quantity,
      ci.unitPrice
    ));

    return new Order(
      OrderId.generate(),
      OrderStatus.Draft,
      items,
      customer.id,
      customer.defaultShippingAddress
    );
  }
}

8.5.9 Specification(仕様)

複雑な条件をオブジェクト化 するパターン。クエリ条件・バリデーション・ビジネスルールに使える。

interface Specification<T> {
  isSatisfiedBy(candidate: T): boolean;
  and(other: Specification<T>): Specification<T>;
  or(other: Specification<T>): Specification<T>;
  not(): Specification<T>;
}

class PremiumCustomerSpec implements Specification<Customer> {
  isSatisfiedBy(customer: Customer): boolean {
    return customer.totalPurchases.greaterThan(new Money(100000, JPY)) &&
           customer.registeredYearsAgo() >= 2;
  }
  // ...
}

// 使用
const spec = new PremiumCustomerSpec()
  .and(new JapaneseCustomerSpec())
  .and(new ActiveCustomerSpec().not());

const targetCustomers = allCustomers.filter(c => spec.isSatisfiedBy(c));

8.6 DDD のレイヤアーキテクチャ

DDD では典型的な 4 層アーキテクチャを使う。

【図DDD-5】DDD のレイヤアーキテクチャ:

graph TD UI[プレゼンテーション層 UI Controller] App[アプリケーション層 Use Case Orchestration] Domain[ドメイン層 Entity VO Aggregate Domain Service] Infra[インフラ層 DB 外部API Message Bus] UI --> App App --> Domain Infra -.実装.-> Domain App --> Infra

依存のルール(Clean Architecture と同じ):

  • Domain 層は何にも依存しない(純粋な業務ロジック)
  • Infra は Domain のインターフェースを実装(依存性逆転)
  • App は Domain と Infra(インターフェース)を使う
  • UI は App を呼ぶ

8.7 Event Storming

Alberto Brandolini が 2013 年頃に提唱した、付箋紙でドメインを可視化するワークショップ手法。DDD の最強の入門ツール。

使う付箋の色と意味

意味
オレンジ ドメインイベント(OrderPlacedPaymentFailed)過去形
コマンド(PlaceOrderCancelSubscription)命令形
黄色 アクター(顧客、管理者、システム)
ポリシー / ルール(「支払失敗なら 3 日後に再試行」)
ピンク 外部システム(決済 API、メール送信)
読み取りモデル(注文一覧、月次レポート)
ホットスポット(疑問、リスク、議論が必要な箇所)

ワークショップの流れ

  1. カオス的に発散:業務エキスパートが思いつくイベントを壁に貼る
  2. 時間順に並べる:左から右へ時系列
  3. 因果関係を見つける:何がトリガーか
  4. コマンドとアクターを紐付ける
  5. Aggregate 境界を発見:関連イベントをグループ化
  6. Bounded Context を抽出:自然な切れ目を見つける

実例:EC の Event Storming

[顧客][カートに追加] → CartItemAdded
[顧客][チェックアウト] → CheckoutStarted
[システム][在庫確認] → InventoryChecked
  → 在庫OK? → Yes → [決済依頼] → PaymentRequested
              → No  → OutOfStockNotified
[決済API] → PaymentApproved / PaymentDeclined
PaymentApproved → [注文確定] → OrderPlaced
OrderPlaced → [倉庫に通知] → ShippingRequested
[倉庫] → ShippingPrepared → ItemShipped → ItemDelivered

この流れから、以下の Bounded Context が見える:

  • カート:CartItemAdded、CheckoutStarted
  • 決済:PaymentRequested、PaymentApproved
  • 注文:OrderPlaced
  • 配送:ShippingRequested、ItemShipped、ItemDelivered
  • 在庫:InventoryChecked、OutOfStockNotified

8.8 DDD と Clean Architecture の関係

Clean Architecture(Robert C. Martin)と DDD は 互換・補完関係

【図DDD-6】DDD × Clean Architecture:

graph TD subgraph Clean[Clean Architecture 層] CUI[UI] CApp[Application] CDomain[Domain] CInfra[Infrastructure] end subgraph DDD[DDD 要素] DE[Entity] DV[Value Object] DA[Aggregate] DS[Domain Service] DR[Repository Interface] DEv[Domain Event] end CDomain -.配置.-> DE CDomain -.配置.-> DV CDomain -.配置.-> DA CDomain -.配置.-> DS CDomain -.配置.-> DR CDomain -.配置.-> DEv

Clean Architecture は 「どう層を分けるか」、DDD は 「ドメイン層で何を書くか」 を示す。セットで使うのが現代的。

8.9 DDD と CQRS / Event Sourcing

DDD の戦術パターンは CQRS・Event Sourcing と強い親和性 を持つ。

組み合わせのメリット:

  • Aggregate = コマンドサイドの整合性境界
  • Domain Event = Event Sourcing のイベントそのもの
  • Read Model = コンテキスト別のビュー
  • Bounded Context = マイクロサービスの単位

【図DDD-7】DDD + CQRS + ES の関係:

graph LR Client[クライアント] CmdAPI[Command API] Agg[Aggregate ドメインロジック] EventStore["Event Store イベント列"] Projector[Projector] ReadDB["Read DB"] QueryAPI[Query API] Client --> CmdAPI CmdAPI --> Agg Agg -.Domain Events.-> EventStore EventStore -.stream.-> Projector Projector --> ReadDB Client --> QueryAPI QueryAPI --> ReadDB

ただし 3 つを全部採用すると複雑度が爆発するので、コアドメインのみ で検討するのが賢明。

8.10 DDD 導入ステップ

ステップ 1:ユビキタス言語から始める

DDD 全部を一気に入れる必要はない。まず業務エキスパートと会話して、用語集 を作る。それだけでも効果大。

ステップ 2:Event Storming で可視化

壁に付箋を貼ってドメインを可視化。1-2 日のワークショップで大きく理解が進む。

ステップ 3:Bounded Context を見極める

既存システムのどこが混ざっているかを発見。Context Map を描く。

ステップ 4:コアドメインに戦術パターン適用

すべてに DDD を適用しない。コアドメインのみ に集中。

ステップ 5:Anti-Corruption Layer で外界から守る

レガシー・外部 API から自分のドメインを守る ACL を設置。

ステップ 6:必要なら CQRS / ES へ進化

十分複雑なら CQRS や Event Sourcing を検討。

8.11 DDD アンチパターン

アンチ 1:Anemic Domain Model(貧血ドメインモデル)

データだけ持ちロジックがない Entity。サービスクラスにロジックが集中し、結果的に手続き型。

悪い:

class Order {
  constructor(public id: string, public items: any[], public status: string) {}
}

class OrderService {
  placeOrder(order: Order) {
    if (order.items.length === 0) throw new Error("Empty");
    order.status = "placed";
  }
}

良い:

class Order {
  place() {
    if (this.items.length === 0) throw new Error("Empty");
    this.status = OrderStatus.Placed;
  }
}

アンチ 2:DDD Lite(戦術パターンだけ真似る)

Entity、Repository を作るだけで、Ubiquitous Language や戦略的 DDD を無視。形だけ DDD。

アンチ 3:万能 DDD

すべてのコードに DDD を適用。単純な CRUD にまで Entity・Aggregate・Repository を作る過剰設計。

アンチ 4:巨大 Aggregate

1 つの Aggregate に全てを詰め込む。性能劣化、ロック競合、複雑化。

アンチ 5:Context の混在

複数のコンテキストのモデルが混在した巨大クラス(God Customer)。

アンチ 6:ORM ファースト

ORM のテーブル構造からクラスを生成して、「ドメイン駆動」と呼ぶ。実態は Database-Driven

8.12 言語別実装のヒント

Java(Spring Boot + JPA)

  • Spring の DI で Clean Architecture を実現
  • JPA @Entity はドメインに侵食する危険あり、Persistence Model と Domain Model を分離 推奨
  • Axon Framework が CQRS/ES 対応

TypeScript / Node.js

  • class + 型システムで表現豊か
  • ts-patternzod でバリデーション
  • NestJS が DDD フレンドリ

Go

  • 小さな構造体と インターフェースで表現
  • パッケージ単位で Bounded Context を分ける
  • go-clean-architecture 系テンプレート多数

Rust

  • 所有権・型システムが DDD と超相性良い
  • newtype パターンで Value Object
  • Rust DDD コミュニティが活発

C# / .NET

  • DDD 元祖の Java 系と並んで歴史あり
  • MediatR(CQRS)、MartenDB(Event Store)、EventFlow
  • Microsoft 公式が DDD サンプル提供

8.13 DDD ツール・ライブラリ

カテゴリ ツール
モデリング Miro / Mural(Event Storming)、draw.io
コンテキストマップ Context Mapper DSL
イベントストア EventStoreDB、Kafka、Axon Server
フレームワーク Axon(Java)、NEventStore(.NET)、Marten(.NET)
プロジェクション Kafka Streams、Flink、ksqlDB

8.14 DDD が解決する問題

DDD を正しく適用すると、以下の問題が緩和される:

  • 用語の不一致:ユビキタス言語で解決
  • ドメイン知識のサイロ化:業務エキスパートとの協働
  • Big Ball of Mud:Bounded Context で分離
  • Anemic Model による複雑性爆発:戦術パターンで凝集
  • マイクロサービス分割の失敗:Context Map で論理的分割
  • レガシー統合の汚染:ACL で防御
  • 変更の困難さ:モデルとコードの一致で保守性向上

MVC / MVP / MVVM

初心者向けメモ: Web・モバイル開発でよく聞く MVC・MVP・MVVM は、UI を持つアプリケーションの構造パターン です。「View と Model をどう繋ぐか」の 3 つの流派です。

MVC(Model-View-Controller)

User → View → Controller → Model → View
  • Model:データ・ビジネスロジック
  • View:表示
  • Controller:入力を受けて Model 更新、View 選択

採用例: Ruby on Rails、Django、Spring MVC、Laravel、ASP.NET MVC

MVP(Model-View-Presenter)

View と Model が直接やり取りしない。Presenter が仲介。

採用例: 古典的 Windows Forms、Android(古典的)

MVVM(Model-View-ViewModel)

データバインディングで View と ViewModel を自動同期。

採用例: WPF、SwiftUI(類似)、Vue、Angular(一部)、Knockout、React 初期

【図10】MVC/MVP/MVVM の違い:

graph TD subgraph MVC V1[View] --> C1[Controller] C1 --> M1[Model] M1 --> V1 end subgraph MVP V2[View] --> P2[Presenter] P2 --> M2[Model] P2 --> V2 end subgraph MVVM V3[View] <--> VM3[ViewModel data binding] VM3 --> M3[Model] end

マイクロサービスアーキテクチャ

初心者向けメモ: マイクロサービスは「1 つの大きなアプリを、小さな独立したサービス群に分割する」アーキテクチャです。Netflix、Amazon、Google のような大規模システムが採用し、「今風」のイメージが強いですが、複雑さ・運用コストは大きく、小〜中規模では過剰になりがちです。

定義

Martin Fowler & James Lewis の定義(2014):

Microservices is an architectural style that structures an application as a collection of small, autonomous services, modeled around a business domain.

特徴

  1. 独立デプロイ可能:サービスごとに別々にリリース
  2. 境界は明確:各サービスは独自の DB・API を持つ
  3. 技術の多様性:Node.js、Java、Go、Rust を混在可
  4. ビジネスドメインに沿う:技術レイヤではなく業務機能で分割
  5. 小さなチーム:「2 枚のピザ」ルール(8-10 人)

典型的構成

【図11】マイクロサービスアーキテクチャ:

graph TD Client[クライアント Web Mobile] GW[API Gateway 認証 ルーティング] subgraph Services User[User Service] Order[Order Service] Inventory[Inventory Service] Payment[Payment Service] Notification[Notification Service] end subgraph DataStores UserDB["User DB"] OrderDB["Order DB"] InvDB["Inventory DB"] PayDB["Payment DB"] end MQ[Message Queue Kafka] Client --> GW GW --> User GW --> Order Order --> Inventory Order --> Payment Order --> Notification Order -.-> MQ Notification -.-> MQ User --> UserDB Order --> OrderDB Inventory --> InvDB Payment --> PayDB

マイクロサービスのメリット

  • 独立スケール:負荷の高いサービスだけスケールアウト
  • 技術の自由度:言語・フレームワーク・DB を用途別に最適化
  • 障害隔離:1 サービス障害が全体停止に直結しない
  • 組織スケール:数百人チームが並行開発可能

マイクロサービスの課題

  • 運用複雑度:数十〜数百のサービスの管理
  • 分散トランザクション:ACID が効かない、Saga パターン必須
  • ネットワーク遅延:関数呼び出しが HTTP/gRPC 呼び出しに
  • デバッグ困難:分散トレーシング必須
  • データ整合性:Eventually Consistent が基本
  • コスト増:インフラ、人材、ツール
  • テスト困難:結合テストが複雑

マイクロサービスの必須ツールチェーン

領域 ツール
コンテナ Docker、containerd
オーケストレータ Kubernetes
サービスメッシュ Istio、Linkerd、Consul Connect
API Gateway Kong、Envoy、AWS API Gateway
メッセージング Kafka、RabbitMQ、NATS、SQS
分散トレーシング Jaeger、Zipkin、OpenTelemetry
メトリクス Prometheus、Grafana
ログ集約 Elasticsearch + Kibana、Loki
サービスディスカバリ Consul、etcd、Kubernetes DNS
設定管理 Spring Cloud Config、AWS Parameter Store
Secrets HashiCorp Vault、AWS Secrets Manager
CI/CD Argo CD、Flux、GitHub Actions

分散システムの誤謬(8 Fallacies)

マイクロサービスを設計する前に知るべき、Peter Deutsch による警告(1994-97):

  1. ネットワークは信頼できる
  2. レイテンシはゼロ
  3. 帯域は無限
  4. ネットワークはセキュア
  5. トポロジーは変わらない
  6. 管理者は 1 人
  7. 転送コストはゼロ
  8. ネットワークは均質

全部 間違い。これを知らずに分散化すると地獄を見る。


イベント駆動アーキテクチャ

初心者向けメモ: イベント駆動アーキテクチャ(EDA)は、「サービス同士が直接呼び合う」のではなく、「イベントを発行し、それに反応する」方式です。疎結合・非同期・スケーラブルが特徴で、リアルタイム性・拡張性が求められる現代システムの必須パターンです。

基本構造

【図12】イベント駆動アーキテクチャ:

graph TD Publisher[イベント発行者] Broker[Event Broker Kafka EventBridge NATS] Sub1[Subscriber 1] Sub2[Subscriber 2] Sub3[Subscriber 3] Publisher --> Broker Broker --> Sub1 Broker --> Sub2 Broker --> Sub3

2 つの主要パターン

1. Event Notification(イベント通知)

「何かが起きた」を通知するだけ。受信側が必要なら別途情報を取りに行く。

OrderPlaced { orderId: "123" }

2. Event-Carried State Transfer(状態転送)

イベント内に完全な情報を含める。受信側は追加クエリ不要。

OrderPlaced {
  orderId: "123",
  customer: { ... },
  items: [ ... ],
  total: 5000,
  timestamp: "..."
}

メッセージブローカ

ブローカ 特徴 用途
Apache Kafka 高スループット、永続化 ログ・分析・ストリーミング
RabbitMQ AMQP、機能豊富 タスクキュー、RPC
NATS 軽量、高速 マイクロサービス内部
AWS SQS マネージド、FIFO AWS 内サービス連携
AWS EventBridge スキーマレジストリ AWS イベントバス
Google Pub/Sub グローバル、マネージド GCP
Azure Event Grid マネージド Azure
Redis Streams 軽量、Redis 統合 小規模

Push vs Pull

  • Push(Webhooks 等):発行者が受信者を呼ぶ。シンプルだが失敗時再送困難
  • Pull(Kafka):受信者がメッセージを取りに来る。スケール・耐障害性に優れる

イベント駆動のメリット

  • 疎結合:発行者は誰が聞いているか知らない
  • 非同期:遅いサービスが速いサービスを止めない
  • 拡張性:新しい購読者を追加しても既存に影響なし
  • 耐障害性:ブローカがメッセージをバッファ

イベント駆動の課題

  • デバッグ困難:非同期フロー追跡が難しい
  • 結果整合性:「即座に反映」は期待できない
  • 順序保証:分散環境では難しい
  • 重複配信:At-least-once が一般的、冪等性必須
  • スキーマ進化:イベント形式変更は慎重に

CQRS と Event Sourcing

初心者向けメモ: CQRS は「書き込みと読み込みを別モデルに分ける」、Event Sourcing は「状態でなくイベントの連なりを保存する」パターンです。高度で強力ですが、複雑さが大きいので適用範囲を見極めることが重要。

CQRS(Command Query Responsibility Segregation)

コマンド(書き込み)クエリ(読み込み)別モデル で扱う。

【図13】CQRS:

graph TD Client[クライアント] CmdAPI[Command API] QueryAPI[Query API] WriteModel[Write Model 正規化 DB] ReadModel[Read Model 非正規化 ビュー] Client --> CmdAPI Client --> QueryAPI CmdAPI --> WriteModel WriteModel -.イベント.-> ReadModel QueryAPI --> ReadModel

メリット:

  • 読み取り最適化(非正規化ビュー)
  • 書き込み整合性(正規化モデル)
  • 読み書きが別個にスケール
  • 複雑な検索に特化したリードモデル

Event Sourcing

現在の状態ではなく、状態変化(イベント)の履歴 を保存する。

従来:口座残高 = 10,000 円(1 レコード)
Event Sourcing:
  AccountOpened (初期 0 円)
  Deposited (+5,000 円)
  Deposited (+10,000 円)
  Withdrawn (-5,000 円)
  = 現在 10,000 円

メリット

  • 完全な監査証跡:全変更履歴が残る(金融・医療で必須)
  • 過去の状態を再現:任意時点の状態を計算可能
  • 時間方向のデバッグ:「なぜこうなったか」を追える
  • 複数のビューを作成可能:異なるリードモデルを同じイベントから生成
  • ビジネス分析:イベント自体が分析対象

Event Sourcing + CQRS の組み合わせ

【図14】Event Sourcing + CQRS:

graph LR Client[クライアント] CmdHandler[Command Handler] EventStore["Event Store イベントの追記ログ"] Projector[Projector] ReadDB["Read DB 非正規化"] QueryAPI[Query API] Client --> CmdHandler CmdHandler --> EventStore EventStore -.stream.-> Projector Projector --> ReadDB Client --> QueryAPI QueryAPI --> ReadDB

向くケース・向かないケース

向くケース:

  • 金融、会計、銀行(監査要求)
  • 医療記録
  • ゲーム(リプレイ機能)
  • 複雑なドメイン(DDD と相性良い)
  • 時間ベース分析が必要

向かないケース:

  • 単純な CRUD アプリ
  • イベント数が非常に少ない
  • チームが慣れていない
  • リードモデルの再構築コストが許容できない

主要実装

  • EventStoreDB:Event Sourcing 専用 DB
  • Apache Kafka:イベントストリームとして
  • Axon Framework(Java)
  • MartenDB(.NET、Postgres ベース)

サーバレスアーキテクチャ

初心者向けメモ: サーバレスは「サーバを自分で管理しない」アーキテクチャ。関数(Function)単位でコードをアップロードすれば、クラウドが実行してくれます。使った分だけ課金、使わなければゼロ円。小〜中規模のスパイキーなワークロードに最適です。

サーバレスの 2 モデル

1. FaaS(Function as a Service)

個別の関数をアップロード。イベント発生時に実行。

  • AWS Lambda:業界標準
  • Google Cloud Functions
  • Azure Functions
  • Cloudflare Workers:V8 Isolate、低レイテンシエッジ
  • Deno Deploy
  • Vercel Functions

2. BaaS(Backend as a Service)

マネージド DB、認証、ストレージ等を組み合わせて作る。

  • Firebase
  • Supabase
  • AWS Amplify

典型例:サーバレス画像処理

【図15】サーバレス画像処理:

graph TD User[ユーザー] CDN[CloudFront CDN] S3[S3 元画像] Lambda[Lambda 画像変換] S3Out[S3 変換済み] User --> CDN CDN --> S3Out User -.-> S3 S3 -.upload event.-> Lambda Lambda --> S3Out

メリット

  • 運用ゼロ:サーバ管理、OS パッチ、スケーリング不要
  • 課金明確:使用時間・呼び出し回数のみ
  • 自動スケール:ゼロから数万同時実行まで
  • 短時間開発:個別機能を素早くリリース

課題

  • Cold Start:初回実行時の起動遅延(数百 ms〜数秒)
  • 実行時間制限:AWS Lambda は 15 分まで
  • 状態を持てない:ステートレス必須
  • ベンダロックイン:抽象化レイヤ(Serverless Framework 等)で緩和
  • デバッグ難:ローカル再現が難しい
  • 複雑な依存関係:パッケージサイズ制限

サーバレスが向くケース

  • Web API のバックエンド(トラフィックが変動)
  • バッチ処理・cron
  • イベント処理(S3 アップロード、DB 変更)
  • Webhook 受信
  • チャットボット
  • スケジュールタスク
  • 画像・動画処理

サーバレスが向かないケース

  • 常時稼働の長時間処理
  • WebSocket を多用する常時接続
  • 超低遅延要求(ms 以下)
  • 高度なカスタム設定が必要

マイクロフロントエンド

初心者向けメモ: フロントエンドでも、バックエンドのマイクロサービスと同様に「大きな SPA を分割する」手法が 2020 年頃から普及しました。それがマイクロフロントエンドです。複数チームが並行開発できる一方、複雑さは増します。

主な実装方式

  1. Module Federation(Webpack 5):ランタイムでモジュール読み込み
  2. Web Components:標準技術で独立コンポーネント
  3. iframe:最も単純だが UX に問題
  4. Server-side CompositionSSR で統合(Next.js、Nuxt)
  5. Single-SPA:ルータ統合型

採用例: Spotify、IKEA、DAZN、Zalando


API 設計

初心者向けメモ: API(Application Programming Interface)は、異なるシステム同士を繋ぐ「契約」です。どう設計するかで、使いやすさ・パフォーマンス・拡張性が大きく変わります。ここでは主要 3 方式を比較します。

REST(Representational State Transfer)

Roy Fielding が 2000 年の博士論文で提唱。HTTP の特性を活かす。

GET    /users         一覧取得
GET    /users/123     個別取得
POST   /users         作成
PUT    /users/123     更新
DELETE /users/123     削除

原則:

  • リソース指向:URL はリソースを表す
  • HTTP メソッドで動作表現
  • ステータスコード:200, 201, 400, 401, 404, 500
  • ステートレス:各リクエストは独立
  • HATEOAS(理想):レスポンスに次のアクションへのリンク

GraphQL

Facebook が 2015 年に公開。クライアントが欲しいデータだけをクエリできる

query {
  user(id: "123") {
    name
    email
    posts(first: 10) {
      title
      createdAt
    }
  }
}

メリット:

  • Over-fetching / Under-fetching 問題を解決
  • 型システム(スキーマ)
  • 単一エンドポイント

デメリット:

  • キャッシュが難しい(GET でなく POST)
  • N+1 問題(解決策:DataLoader)
  • 複雑なクエリによる DoS リスク

実装: Apollo、Relay、Hasura、URQL

gRPC

Google が 2015 年に公開。Protocol Buffers で定義、HTTP/2 で高速通信。

syntax = "proto3";

service UserService {
  rpc GetUser(GetUserRequest) returns (User);
  rpc StreamUsers(StreamRequest) returns (stream User);
}

message User {
  string id = 1;
  string name = 2;
  string email = 3;
}

メリット:

  • バイナリ、高速
  • 双方向ストリーミング対応
  • 言語中立(Go、Java、Python、C++ 等)
  • 型安全、コード自動生成

デメリット:

  • ブラウザ直接対応弱(gRPC-Web が必要)
  • デバッグしにくい
  • テキスト形式でない

比較表

項目 REST GraphQL gRPC
プロトコル HTTP/1.1, HTTP/2 HTTP(通常 POST) HTTP/2
データ形式 JSON(通常) JSON Protobuf(バイナリ)
スキーマ OpenAPI(任意) 必須 必須
クライアント 任意 クエリ言語 自動生成
ブラウザ △(gRPC-Web)
マイクロサービス間
リアルタイム ✕(SSE/WS 別) Subscription ストリーミング
学習コスト 中-高
典型用途 公開 API BFF、モバイル 内部通信

API ゲートウェイと BFF

API Gateway:クライアントとサービス群の間の 唯一の入口。認証、ルーティング、レート制限、ログを集約。

BFF(Backend for Frontend):Web / Mobile / スマートTV など、クライアント種別ごとに異なる API を提供する中間層。

【図16】API Gateway と BFF:

graph TD Web[Web クライアント] Mobile[Mobile クライアント] TV[TV クライアント] WebBFF[Web BFF] MobileBFF[Mobile BFF] TVBFF[TV BFF] Gateway[API Gateway] S1[Service 1] S2[Service 2] S3[Service 3] Web --> WebBFF Mobile --> MobileBFF TV --> TVBFF WebBFF --> Gateway MobileBFF --> Gateway TVBFF --> Gateway Gateway --> S1 Gateway --> S2 Gateway --> S3

API バージョニング

  • URL/v1/users/v2/users
  • ヘッダAccept: application/vnd.myapi.v2+json
  • クエリパラメータ/users?version=2/users?version=2

ベストは URL(明示的、ログに残る)。


データアーキテクチャ

初心者向けメモ: データは現代システムの心臓です。「どこに、どう置くか」の選択が、性能・スケーラビリティ・コストのすべてに直結します。ここでは典型的な選択肢とパターンを整理します。

データベース種類

種類 代表 用途
リレーショナル(RDB) PostgreSQL、MySQL、SQL Server、Oracle トランザクション、関係性
ドキュメント MongoDB、Couchbase、Firestore 柔軟なスキーマ、JSON
キーバリュー Redis、DynamoDB、Memcached キャッシュ、セッション
列指向 Cassandra、HBase、ScyllaDB ビッグデータ書き込み
グラフ Neo4j、Neptune、ArangoDB SNS、レコメンド
時系列 InfluxDB、TimescaleDB、Prometheus メトリクス、IoT
全文検索 Elasticsearch、Meilisearch 検索エンジン
Vector DB Pinecone、Weaviate、pgvector 埋め込み、RAG
NewSQL Spanner、CockroachDB、TiDB、YugabyteDB 分散 RDB
OLAP Snowflake、BigQuery、Redshift データウェアハウス

データアーキテクチャのパターン

1. Database per Service(マイクロサービス)

各サービスが独自の DB を持つ。他サービスのテーブルに直接アクセスしない。

2. Shared Database(モノリス・共有 DB)

1 つの DB に全データ。シンプルだがスケールの天井。

3. CQRS + Event Sourcing

(前述)書き込み用と読み込み用を分離。

4. Data Lake / Data Warehouse / Lakehouse

【図17】現代のデータアーキテクチャ:

graph TD Source[ソース OLTP SaaS IoT] ETL[ETL ELT ingestion] Lake[Data Lake S3 GCS 生データ Parquet] WH[Data Warehouse Snowflake BigQuery 構造化] BI[BI Tableau Looker] ML[ML 学習 推論] Source --> ETL ETL --> Lake Lake --> WH WH --> BI Lake --> ML

Lakehouse(Delta Lake、Iceberg、Hudi)は Lake と WH の良いとこ取り。

シャーディング

データを複数 DB ノードに分散。

  • Range Sharding:ID 範囲で分割
  • Hash Sharding:ハッシュで分割(均等だが範囲クエリ不可)
  • Geographic Sharding:地域で分割

レプリケーション

  • Primary-Replica(旧 Master-Slave):書き込みは 1 台、読み取りは複数
  • Multi-Primary:複数ノードで書き込み可(競合解決が難しい)

CDC(Change Data Capture)

DB の変更を検知してイベントストリームに流す。DebeziumMaxwell が有名。


キャッシング戦略

初心者向けメモ: 「遅いものを速くする」最もコスパの良い方法がキャッシュです。ただし「整合性」との戦いになります。正しいキャッシュ戦略を選ばないと、古いデータが見える等の問題が起きます。

キャッシュの階層

  1. CPU キャッシュ(L1/L2/L3)
  2. RAM / ブラウザキャッシュ
  3. CDN(CloudFront、Cloudflare、Fastly)
  4. リバースプロキシ(nginx、Varnish)
  5. アプリケーションキャッシュ(Redis、Memcached)
  6. DB キャッシュ(クエリキャッシュ、バッファプール)

主要パターン

1. Cache-Aside(Lazy Loading)

読み込み:
  1. キャッシュ確認
  2. ヒットなら返す
  3. ミスなら DB から取得 → キャッシュに保存 → 返す

書き込み:
  1. DB 更新
  2. キャッシュ無効化 or 更新

最も一般的。シンプル。

2. Read-Through

アプリはキャッシュのみを知る。キャッシュが DB から自動取得。

3. Write-Through

書き込みはキャッシュ → 同期的に DB。データ一貫性高いが遅い。

4. Write-Behind / Write-Back

書き込みはキャッシュ → 非同期に DB。速いが障害時ロストリスク。

5. Refresh-Ahead

TTL 切れ前に自動リフレッシュ。

無効化戦略

  • TTL(Time-To-Live):一定時間で失効
  • Event-Based:DB 変更時にパブリッシュ
  • Manual:アプリが明示的に削除

「Cache Invalidation Is Hard」

Phil Karlton の有名な格言:

There are only two hard things in Computer Science: cache invalidation and naming things. コンピュータサイエンスで本当に難しいのは 2 つだけ:キャッシュ無効化と名前付け。

典型的な問題

  • Thundering Herd(雷鳴問題):TTL 切れで大量リクエストが DB を襲う
  • Cache Stampede:同上、解決策は lock、probabilistic early expiration
  • Cache Penetration:存在しないキーで DB に毎回問合せ(対策:Negative cache、Bloom filter)
  • Cache Avalanche:複数キーが同時失効 → DB 過負荷

メッセージングパターン

初心者向けメモ: サービス間通信は「同期」と「非同期」の 2 種類。メッセージングは非同期の王道です。ここでは典型的な 5 パターンを整理します。

1. Queue(P2P)

1 つのメッセージは 1 つの Consumer のみ受信。タスクキュー向き。

2. Topic / Pub-Sub

1 つのメッセージを複数の Subscriber が受信。イベント通知向き。

3. Request-Reply

非同期だが、相手の応答を待つパターン。通信コストで難しい。

4. Competing Consumers

同じキューを複数 Consumer が読んで負荷分散。

5. Saga パターン

マイクロサービスで分散トランザクションを表現するパターン。補償トランザクション で失敗時の取り消しを定義。

【図18】Saga パターン(Orchestration 型):

sequenceDiagram participant O as Orchestrator participant Order as Order Service participant Pay as Payment Service participant Inv as Inventory Service O->>Order: Create Order Order-->>O: OK O->>Pay: Charge Card Pay-->>O: Failed O->>Order: Cancel Order Note over O,Inv: 補償アクション

配信保証

  • At-most-once:0 or 1 回(喪失の可能性)
  • At-least-once:1 回以上(重複の可能性、冪等性が必要)
  • Exactly-once:ちょうど 1 回(最も難しい、Kafka Transactions など)

スケーラビリティパターン

初心者向けメモ: スケーラビリティには 垂直(Vertical)水平(Horizontal) の 2 軸があります。垂直は「サーバを強くする」、水平は「サーバを増やす」。クラウド時代は水平が主流です。

Vertical vs Horizontal Scaling

【図19】スケーラビリティの 2 方向:

graph LR Small[小サーバ] Big[大サーバ 垂直スケール] Many[多数サーバ 水平スケール] Small --> Big Small --> Many

ロードバランサ

アルゴリズム:

  • Round Robin:順番
  • Least Connections:接続数最少へ
  • IP Hash:IP ベース、同じユーザーは同じサーバへ
  • Weighted:サーバ性能で重み付け
  • Consistent Hash:サーバ増減時の再配置最小

ステートレス設計

水平スケールの前提。セッションを DB・Redis に外出し、サーバはステートレスに。

非同期化

「同期的にやる必要がない処理」はキューに入れる。

読み取り分離

Primary-Replica で読み取り専用スケール。

シャーディング

データレベルの水平分割。

CDN

静的コンテンツを世界中のエッジに配信。

Auto Scaling

指標(CPU、メモリ、リクエスト数、カスタムメトリクス)に応じた自動増減。


可用性パターン

初心者向けメモ: 「99.9% の可用性」と聞くと高そうですが、年間 8.76 時間の停止を許容します。99.99% なら 52 分、99.999%(ファイブナイン)なら 5 分。数字の違いは大きく、投資コストも桁違いです。

可用性の計算

99.9%    (スリーナイン)  年 8.76 時間の停止
99.95%                   年 4.38 時間
99.99%   (フォーナイン)  年 52.699.999%  (ファイブナイン) 年 5.26

SLA / SLO / SLI

  • SLI(Service Level Indicator):実測値
  • SLO(Service Level Objective):社内目標
  • SLA(Service Level Agreement):顧客契約

Redundancy(冗長化)

【図20】可用性の冗長化階層:

graph TD NoRedundancy[冗長なし] Process[プロセス冗長 同一サーバ] Server[サーバ冗長 同一リージョン] AZ[AZ 冗長 マルチ AZ] Region[リージョン冗長 マルチリージョン] Global[グローバル DNS レベル] NoRedundancy --> Process Process --> Server Server --> AZ AZ --> Region Region --> Global

Active-Active vs Active-Passive

  • Active-Active:全ノードが処理。負荷分散と冗長を兼ねる
  • Active-Passive:1 つが本番、もう 1 つは待機(Hot / Warm / Cold Standby)

Disaster Recovery(DR)

  • RPO(Recovery Point Objective):何時間前まで復旧できるか(データ損失許容)
  • RTO(Recovery Time Objective):どれだけ早く復旧できるか
レベル RPO RTO コスト
Backup & Restore 24h 数時間
Pilot Light 1h 数十分
Warm Standby 数分 数分
Multi-Region Active 即時 最高

サーキットブレーカ(Circuit Breaker)

障害時に呼び出しを 即座に失敗させる パターン。下流の死亡を感知して、一定時間スキップ。Netflix の Hystrix、Resilience4j が有名。

タイムアウト・リトライ・バックオフ

  • Timeout:無限待機を防ぐ
  • Retry:一時的失敗を吸収
  • Exponential Backoff + Jitter:リトライ嵐を防ぐ

Bulkhead(隔壁)

機能ごとに 別々のリソースプール。1 つが落ちても他は影響なし。

Graceful Degradation(段階的劣化)

全部止めるのではなく、重要機能だけ動かす。例:レコメンドが落ちたらデフォルト表示。


分散システムパターン

初心者向けメモ: 分散システムには固有の難しさがあります。CAP 定理、FLP 不可能性、Byzantine Generals など、古典的な理論的制約を知っておくと、設計判断の根拠になります。

CAP 定理

【図21】CAP 定理の三角形:

graph TD C[Consistency 一貫性] A[Availability 可用性] P[Partition Tolerance 分断耐性] CAP[CAP の 3 つ] CAP --> C CAP --> A CAP --> P

分散システムでは 同時に 3 つは満たせない。Partition は避けられないので CP か AP を選ぶ。

  • CP:銀行、予約、Google Spanner
  • AP:SNS タイムライン、Amazon DynamoDB、Cassandra

PACELC 定理

CAP の拡張。「分断時は C or A」に加え、Else(通常時)は Latency or Consistency

一貫性モデル

モデル 意味
Strict Consistency リアルタイム順序保証(実装不可能)
Linearizability SC + リアルタイム(最強の実装可能)
Sequential Consistency スレッドで一貫順序
Causal Consistency 因果関係のみ保証
Eventual Consistency 最終的に収束

合意アルゴリズム

  • Paxos(Lamport 1989):原典
  • Raft(Ongaro 2014):Paxos を分かりやすく、etcd / Consul / TiKV 採用
  • Zab:Apache ZooKeeper
  • PBFT:ビザンチン耐性
  • HotStuff / Tendermint:ブロックチェーン向け

レプリケーション戦略

  • Single-Leader(Primary-Replica):シンプル、Read scale
  • Multi-Leader:Geo 分散、競合解決必要
  • Leaderless(Dynamo-style):Cassandra、DynamoDB

分散トランザクション

  • 2PC(Two-Phase Commit):参加者がブロックする、現代では忌避
  • Saga パターン:補償トランザクションで長時間 TX 実現
  • TCC(Try-Confirm-Cancel):3 段階

Idempotency(冪等性)

分散で 再送が前提 なので、同じ操作を何度実行しても結果が同じになるよう設計。Idempotency-Key ヘッダなど。


認証認可アーキテクチャ

初心者向けメモ: 認証(誰か)と認可(何ができるか)は別物です。現代の Web は「自社で実装」より「IdP(Identity Provider)を活用」が主流。セキュリティ要件とユーザー体験のバランスが重要です。

主要プロトコル

OAuth 2.0 / 2.1

認可の業界標準。「サードパーティに、特定の範囲で操作を許可する」。

User → アプリ → 「Google ログイン」 → Google → アプリに Access Token 発行

主なフロー:

  • Authorization Code + PKCE:Web / モバイル(推奨)
  • Client Credentials:サーバ間
  • Device Code:TV、IoT
  • Resource Owner Password:非推奨
  • Implicit:非推奨(2.1 で削除)

OpenID Connect(OIDC)

OAuth 2.0 の上に 認証 を乗せたプロトコル。ID Token(JWT)を発行。

SAML 2.0

エンタープライズ SSO の標準。XML ベース、OIDC に比べて重い。

JWT(JSON Web Token)

Header.Payload.Signature
  ヘッダ.ペイロード.署名(Base64)

Stateless なトークン。マイクロサービス間で広く使われる。

注意点:

  • 秘密鍵管理:署名鍵漏洩は致命的
  • Revocation が難しい:ブラックリスト or 短命化
  • ペイロード改ざん不可だが読めるので機密情報を入れない

認可モデル

RBAC(Role-Based Access Control)

ロールに権限を紐付け、ユーザーにロールを割当。

Alice → Admin → [read, write, delete]
Bob   → Editor → [read, write]
Carol → Viewer → [read]

ABAC(Attribute-Based Access Control)

属性ベース。より細かい制御可能。

IF user.department == resource.owner.department
   AND resource.confidentiality != "secret"
   AND time.hour IN [9, 18]
THEN ALLOW read

ReBAC(Relationship-Based)

Google Zanzibar / OpenFGA 流。関係を中心に。

alice is owner of document:123
→ alice can edit document:123

認証認可サービス

  • Auth0 / Okta
  • Microsoft Entra ID
  • AWS Cognito
  • Firebase Auth
  • Keycloak(OSS)
  • Supabase Auth(OSS)
  • Clerk(モダン SaaS)

オブザーバビリティ

初心者向けメモ: オブザーバビリティ(観測性)は「システムの内部状態を外部から推測できる度合い」。ログ・メトリクス・トレースの 3 本柱で構成されます。マイクロサービス時代は特に重要です。

3 本柱

【図22】Observability の 3 本柱:

graph TD Obs[Observability] Logs[Logs 何が起きたか イベント] Metrics[Metrics どれくらい起きたか 数値] Traces[Traces リクエストがどこを通ったか] Obs --> Logs Obs --> Metrics Obs --> Traces

Logs

イベントの時系列記録。構造化ログ(JSON)が現代の主流。

{
  "timestamp": "2026-04-24T10:30:45Z",
  "level": "error",
  "service": "order-service",
  "trace_id": "abc123",
  "user_id": "u456",
  "message": "Payment failed",
  "error": "insufficient funds"
}

ツール: Elasticsearch + Kibana(ELK)、Loki、Datadog Logs、Splunk、CloudWatch Logs

Metrics

時系列数値データ。集計・アラートに最適。

4 種類の指標:

  • Counter:増加のみ(リクエスト数)
  • Gauge:現在値(メモリ使用量)
  • Histogram:分布(レスポンス時間)
  • Summary:パーセンタイル

ツール: Prometheus、Grafana、Datadog、CloudWatch Metrics、New Relic

Traces(分散トレーシング)

1 リクエストが複数サービスを通る際の 全経路 を追跡。

flowchart TB R["Request ID: abc123"] --> G["API Gateway (5ms)"] R --> U["User Service (12ms)"] U --> UDB["DB Query (8ms)"] R --> O["Order Service (45ms)"] O --> C["Cache Check (2ms)"] O --> T["DB Transaction (35ms)"]

ツール: Jaeger、Zipkin、OpenTelemetry、Datadog APM、New Relic

OpenTelemetry(OTel)

CNCF Graduated。ベンダ中立の観測データ収集標準。2025-2026 年の業界標準。

4 つのゴールデンシグナル(Google SRE)

すべてのサービスで監視すべき 4 指標:

  1. Latency(遅延)
  2. Traffic(トラフィック量)
  3. Errors(エラー率)
  4. Saturation(飽和度)

RED メソッド

  • Rate:秒間リクエスト数
  • Errors:エラー数
  • Duration:処理時間

USE メソッド

リソースごとに:

  • Utilization:使用率
  • Saturation:待ち行列
  • Errors:エラー数

セキュリティアーキテクチャ

初心者向けメモ: セキュリティは「後付けできない」性質があります。設計段階から組み込む必要があり、多層防御(Defense in Depth) が原則です。

多層防御の例

【図23】多層防御:

graph TD Internet[インターネット] WAF[WAF DDoS 対策] CDN[CDN エッジ] LB[Load Balancer TLS 終端] APIGW[API Gateway 認証 レート制限] App[アプリケーション 入力検証 認可] DB["DB 暗号化 最小権限"] Internet --> WAF WAF --> CDN CDN --> LB LB --> APIGW APIGW --> App App --> DB

原則

  • 最小権限(Least Privilege)
  • Defense in Depth(多層防御)
  • Fail Secure(失敗時は安全側に)
  • Zero Trust(暗黙の信頼をしない)
  • セキュアデフォルト

脅威モデリング

  • STRIDE:Spoofing、Tampering、Repudiation、Information disclosure、Denial of service、Elevation of privilege
  • DREAD:Damage、Reproducibility、Exploitability、Affected users、Discoverability

OWASP Top 10(2025)

  1. Broken Access Control
  2. Cryptographic Failures
  3. Injection
  4. Insecure Design
  5. Security Misconfiguration
  6. Vulnerable and Outdated Components
  7. Identification and Authentication Failures
  8. Software and Data Integrity Failures
  9. Security Logging and Monitoring Failures
  10. Server-Side Request Forgery(SSRF)

暗号化

  • 保存時(at rest):dm-crypt、BitLocker、FileVault、TDE
  • 転送時(in transit)TLS 1.3
  • 使用時(in use):Confidential Computing(TDX、SEV-SNP)

Secret 管理

ハードコード絶対禁止。使うもの:

  • HashiCorp Vault
  • AWS Secrets Manager
  • Google Secret Manager
  • Azure Key Vault
  • 1Password for Developers

テスト戦略

初心者向けメモ: テストはアーキテクチャの重要な一部です。「テストピラミッド」の原則で、底辺(単体テスト)を厚く、頂点(E2E)を薄く保つのが効率的です。

テストピラミッド

【図24】テストピラミッド:

graph TD E2E[E2E 少 遅い 高コスト] Integration[Integration 中] Unit[Unit 多 速い 低コスト] E2E --> Integration Integration --> Unit

テストの種類

種類 範囲 速度 本数目安
Unit 関数 / クラス単位 ms 数千〜
Integration 複数モジュール 数秒 数百〜
Contract API 契約(Pact) 数秒 数十
E2E 全体フロー 数〜数十
Smoke 基本動作確認
Load 負荷 分〜時間 シナリオ数
Chaos 障害注入 実験的 シナリオ数

TDD(Test-Driven Development)

RedGreenRefactor
失敗するテスト書く → 最小限で通す → リファクタ

BDD(Behavior-Driven Development)

Given When Then で仕様を書く(Cucumber、RSpec)
Given ユーザーがログイン済み
When /dashboard にアクセス
Then ダッシュボードが表示される

Mutation Testing

コードを故意に変異させて、テストが検知できるか確認。Stryker、PITest。

Property-Based Testing

「すべての入力で性質が成り立つ」をランダム入力でチェック。QuickCheck、Hypothesis、fast-check。


CI/CD とデプロイパターン

初心者向けメモ: Continuous Integration / Continuous Delivery は、現代開発の必須プラクティスです。「ビルドは常に緑」「デプロイはボタン一発」「小さく頻繁に」が原則。

CI/CD パイプライン例

【図25】CI/CD パイプライン:

graph TD Commit[Git Commit] Lint[Lint Format] Test[Unit Test] Build[Build Docker Image] Scan[Security Scan SBOM] Push[Push to Registry] Deploy[Deploy to Staging] IntegrationTest[Integration Test] Approve[Manual Approval] Prod[Deploy to Production] Commit --> Lint Lint --> Test Test --> Build Build --> Scan Scan --> Push Push --> Deploy Deploy --> IntegrationTest IntegrationTest --> Approve Approve --> Prod

デプロイ戦略

1. Rolling Update

古いインスタンスを少しずつ新しいものに置換。Kubernetes デフォルト。

2. Blue-Green

本番環境を 2 セット持ち、切り替え。即時ロールバック可能。

3. Canary

一部トラフィックを新バージョンへ(例:5%)。メトリクス監視しつつ段階拡大。

4. Feature Flag

コードは全部デプロイ、機能は ON/OFF で制御。LaunchDarkly、Unleash、Split.io

5. Shadow / Mirror

本番トラフィックを新バージョンにも流すが、レスポンスは捨てる。動作確認。

GitOps

Git を単一の真実源(Source of Truth)として、インフラ・アプリをデプロイ。Argo CDFlux が代表。


選び方とトレードオフ

初心者向けメモ: 「マイクロサービス or モノリス」「REST or GraphQL」などの選択は、チームサイズ・ドメイン複雑度・組織成熟度 で決まります。ここでは判断フレームを示します。

規模別推奨

規模 アーキテクチャ データベース デプロイ
〜10人、〜10万ユーザー モノリス RDB 単体 VPS、Render、Railway
10-50人、〜100万ユーザー モジュラモノリス RDB + Redis ECS、Cloud Run
50-200人、〜1000万ユーザー マイクロサービス(少数) RDB + NoSQL 混在 Kubernetes
200人以上、1億ユーザー マイクロサービス+EDA 多種併用 + Data Lake 多リージョン K8s

アーキテクト判断のチェックリスト

  1. 何を最適化するか:速度 / コスト / 品質
  2. 何を捨てるか:全部は無理
  3. 変化の速度:どれくらいの頻度で要求が変わるか
  4. チーム能力:何ができるか
  5. 時間軸:3 年後どうなっているべきか
  6. 可逆性:やめられる判断か

Jeff Bezos の「二方向ドアと一方向ドア」:

  • 可逆(二方向):素早く決める
  • 不可逆(一方向):慎重に決める

2025-2026 最新動向

初心者向けメモ: アーキテクチャは生きた分野で、毎年新しいパラダイムが登場します。以下は 2025-2026 年に特に重要なトピックです。

1. AI ネイティブアーキテクチャ

  • RAG(Retrieval-Augmented Generation)LLM + ベクトル DB で社内知識応答
  • Agent アーキテクチャ:LLM がツールを呼び出して自律行動
  • ベクトル DB 統合:pgvector、Pinecone、Weaviate、Milvus
  • モデルルーティング:リクエスト種別で LLM を使い分け

2. プラットフォームエンジニアリング

  • Internal Developer Platform(IDP):Backstage、Port、Spotify 式
  • Golden Path:チームが標準構成で素早く始められる
  • Platform Team:インフラ・ツールを「製品」として提供

3. サーバレス第 2 世代

  • Durable Functions:ワークフロー指向
  • Cloudflare Workers / Durable Objects:エッジ常駐
  • Deno DeployBun:JavaScript / TypeScript ネイティブ
  • WebAssembly(WASM):サーバレスランタイムの中核

4. モノリス回帰

  • Amazon Prime Video がマイクロサービスを「分散モノリス」に戻して 90% コスト削減(2023 年の記事)
  • Modular Monolith の再評価
  • Majestic Monolith(Basecamp)

5. 型駆動開発・ドキュメント

  • OpenAPIgRPCGraphQLAsyncAPI:スキーマファースト
  • Zod / Pydantic / ts-rest:実行時型検証
  • API Contract Testing:Pact

6. リアルタイム体験

  • WebSocket の進化(Socket.io、SignalR)
  • Server-Sent Events(SSE) で LLM ストリーミング
  • WebRTC:P2P 通信
  • CRDT(Conflict-free Replicated Data Types):Yjs、Automerge、Figma、Notion

7. データ基盤の進化

  • Lakehouse(Delta Lake、Iceberg、Hudi)
  • DuckDB:組み込み分析 DB、爆発的普及
  • Polars:Pandas より速い Rust 製
  • dbt:データ変換の標準

8. Rust / Go / TypeScript 優勢

  • Rustカーネル、CLI、パフォーマンス重視 Web
  • Go:クラウドインフラ、マイクロサービス
  • TypeScript:フロント・Node.js・Deno

9. eBPF とシステム可視化

  • カーネル非侵入で観測・制御
  • Cilium(K8s ネットワーク)、Falco(セキュリティ)、Pixie(観測)

10. 開発者体験(DX)最優先

  • フレームワーク:Next.js、Remix、SvelteKit、Astro、Nuxt 3
  • 即時プレビュー:Vercel、Netlify、Cloudflare Pages
  • AI Copilot 統合:VSCode、Cursor、JetBrains

章の整理

アプリケーションアーキテクチャは、ソフトウェアを「長く使える資産」として作るための設計技法 です。具体的なコードより一段階上の抽象で、チーム・事業・時間との対話を含みます。

本書の要点

  1. アーキテクチャは選択の連続:どれか 1 つが常に正解ということはない
  2. 基本原則を押さえるSOLID、DRY、KISS、YAGNI、関心の分離
  3. スタイルの適材適所:モノリスも立派な選択肢
  4. 非機能要件を意識:性能、可用性、保守性、セキュリティ
  5. 分散は難しい:CAP、Conway、Fallacies を知る
  6. 観測性第一:作る前から監視設計を含める
  7. 進化を続ける:アーキテクチャは一度で決まらない

普遍の真理

  • Simple is better than complex(Pythonic の精神)
  • Premature optimization is the root of all evil(Knuth)
  • Make it work, make it right, make it fast(Kent Beck)
  • The best code is no code at all

2026 年の世界では、AI がコードを書く時代になっても、どういう構造にするか を決める判断力は人間にしかできません。本書があなたのアーキテクチャ旅の良き伴走者となることを願っています。


附録B:代表的デザインパターン集

初心者向けメモ: GoF(Gang of Four)のデザインパターンは古典ですが、現代でもよく使われます。ここでは実務で頻出のパターンを整理します。

B.1 GoF の 23 パターン(抜粋)

生成(Creational)

  • Singleton:唯一のインスタンス
  • Factory Method:生成処理の抽象化
  • Abstract Factory:関連オブジェクト群の生成
  • Builder:複雑なオブジェクトを段階的に構築
  • Prototype:オブジェクトをコピーして生成

構造(Structural)

  • Adapter:互換のないインターフェースを繋ぐ
  • Decorator:動的に機能追加
  • Facade:複雑なサブシステムに単純な窓口
  • Proxy:代理オブジェクト(遅延ロード、アクセス制御)
  • Composite:木構造を統一的に扱う
  • Bridge:実装と抽象を分離

振る舞い(Behavioral)

  • Observer:変化を通知
  • Strategy:アルゴリズムを切替可能に
  • Command:操作をオブジェクト化
  • State:状態によって振る舞い変化
  • Iterator:コレクション走査の抽象化
  • Template Method:骨格を定義、詳細はサブクラス
  • Chain of Responsibility:責務の連鎖

B.2 エンタープライズパターン(Martin Fowler)

  • Repository:データアクセス抽象化
  • Unit of Work:変更追跡とトランザクション
  • Domain Model:豊富なドメインロジック
  • Transaction Script:手続き的業務ロジック
  • Data Mapper:ORM の基礎
  • Active Record:データ行 = オブジェクト(Rails)
  • Service Layer:アプリケーションサービス
  • Identity Map:同一エンティティの重複読み込み防止
  • Lazy Load:遅延読み込み
  • Data Transfer Object(DTO):データ運搬専用

B.3 クラウドパターン(Microsoft Cloud Design Patterns)

  • Retry:一時的失敗の再試行
  • Circuit Breaker:障害時即座失敗
  • Bulkhead:リソース隔離
  • Throttling:レート制限
  • Queue-Based Load Leveling:キューでピーク平準化
  • Saga:分散トランザクション
  • Competing Consumers:複数 Consumer で負荷分散
  • Priority Queue:優先度付きキュー
  • Compensating Transaction:失敗時の補償
  • Health Endpoint Monitoring:健康状態公開
  • Sidecar:補助機能を別コンテナに
  • Ambassador:プロキシ的補助コンテナ
  • Strangler Fig:レガシーを段階置換
  • Anti-Corruption Layer:外部汚染防止
  • Gateway Aggregation:複数 API を 1 つに集約
  • Gateway Offloading:共通機能(認証等)を Gateway に
  • Backend for Frontend:クライアント別 API
  • CQRS
  • Event Sourcing
  • Materialized View:リードモデル事前計算

B.4 分散システムパターン

  • Leader Election:リーダー選出
  • Sharding:データ分割
  • Scatter-Gather:並列実行 + 集約
  • Pipeline:段階処理
  • Service Registry / Discovery:動的サービス検出
  • Circuit Breaker(前述)
  • Dead Letter Queue:処理失敗メッセージ保管

B.5 データパターン

  • CQRS
  • Event Sourcing
  • Materialized View
  • Change Data Capture(CDC):DB 変更を イベントに
  • Transactional Outbox:DB 書き込み + イベント送信の原子化
  • Inbox Pattern:冪等なメッセージ処理
  • Shared Database(アンチパターン寄り)
  • Database per Service(マイクロサービス原則)

附録C:アンチパターン集

初心者向けメモ: 「良いパターン」以上に、「避けるべきパターン」を知ることが重要です。以下は有名なアンチパターン。

C.1 構造のアンチパターン

Big Ball of Mud

構造のない、ごちゃ混ぜのコード。最も多い。

God Object / God Class

1 クラスに数千行、全てを知る巨大オブジェクト。

Lasagna Code

層が多すぎて、何をするにも多層を貫通する。

Spaghetti Code

制御フローがあちこちジャンプ、理解不能。

Copy-Paste Programming

同じコードが 10 箇所にある(DRY 違反)。

Golden Hammer

「ハンマーを持っていると、全てが釘に見える」。1 つの技術を全てに適用。

C.2 マイクロサービスのアンチパターン

Distributed Monolith

マイクロサービスに分けたが、デプロイは常に同時 な状態。最悪の結果(モノリスの弱点 + マイクロサービスの複雑度)。

Nano Services

サービスが細かすぎて、1 機能の変更で 10 サービスを同時変更。

Shared Database

マイクロサービスが同じ DB を共有。結合度高すぎ。

Chatty Services

サービス間の呼び出しが多すぎて、1 リクエストで 100 回通信。

Service Call Chain Hell

A → B → C → D → E の長いチェーン。どれか 1 つ落ちると全滅。

C.3 データのアンチパターン

Anemic Domain Model

ドメインクラスがデータだけ持ち、ロジックがサービスに集中(DDD 的にはアンチ)。

SELECT *

必要ないカラムも取得。性能劣化。

N+1 クエリ

SELECT * FROM orders WHERE user_id = 1;    -- 1 回
SELECT * FROM items WHERE order_id = ?;    -- N 回

ORM でよく発生。Eager loading で解決。

Missing Indexes

WHERE / JOIN キーに index なし。全スキャン。

C.4 組織・プロセスのアンチパターン

Developer Blame Culture

障害をエンジニア個人の責任にする。心理的安全性を破壊。

Hero Culture

特定の「エース」だけが全てを知る。バス要因(バスファクタ 1)。

Magic Pixie Dust

「マイクロサービスにすれば解決」「クラウドに行けば解決」など、技術で全て解ける幻想。

Architecture Astronaut

抽象度が高すぎて、実際の問題から乖離した設計者。


附録D:システム設計面接問題集

初心者向けメモ: 大手 IT 企業の技術面接では、システム設計問題が定番です。ここでは頻出問題と解き方のフレームを整理します。

D.1 定番問題

  1. URL 短縮サービス(bit.ly 的)を設計せよ
  2. Twitter のタイムラインを設計せよ
  3. Netflix の動画配信を設計せよ
  4. Uber のマッチングを設計せよ
  5. Instagram のストーリーを設計せよ
  6. チャットアプリ(WhatsApp)を設計せよ
  7. 検索エンジン(Google)を設計せよ
  8. レート制限システムを設計せよ
  9. ニュースフィードを設計せよ
  10. 通知システムを設計せよ

D.2 解き方のフレーム(45 分想定)

  1. 要件確認(5 分)

    • 機能要件:何ができる必要があるか
    • 非機能要件:QPS、データ量、SLA
  2. 規模見積(5 分)

    • 月間アクティブユーザー
    • QPS(平均・ピーク)
    • ストレージ(1 年で何 TB)
    • 帯域(MB/s)
  3. 高レベル設計(10 分)

    • クライアント、ロードバランサ、API、DB、キャッシュ、キューのブロック図
  4. データモデル(5 分)

  5. 詳細設計(15 分)

    • キー機能のフロー
    • ボトルネック分析
    • スケーリング戦略
  6. トレードオフ議論(5 分)

    • 選択肢の比較
    • CAP でどちらを優先
    • コスト対効果

D.3 URL 短縮サービスの解き方例

要件:

  • 長 URL → 短 URL(例:https://bit.ly/abc123)
  • リダイレクト
  • 月 1 億 URL 作成、10 億リダイレクト

規模見積:

  • QPS:1 億 / 30 日 / 86400 秒 ≈ 40 QPS 作成
  • リダイレクト QPS:10 億 / 2.5M 秒 ≈ 400 QPS
  • 5 年で 60 億 URL、1 URL = 500 bytes → 3TB

設計:

Client → Load Balancer → API Servers → Cache (Redis) → DB (Cassandra / DynamoDB)
                                        ↓
                                    Counter Service (Zookeeper)

キー生成:

  • Base62 エンコード(0-9, a-z, A-Z)
  • 7 文字で 62^7 ≈ 3.5 兆通り

ボトルネック:

  • リダイレクトが多い → キャッシュ重視
  • キー衝突 → Counter Service で一意性保証

附録E:モノリス→マイクロサービス移行戦略

初心者向けメモ: 「うちもマイクロサービスにしたい」という話はよくありますが、失敗事例の方が多い のが現実です。ここでは慎重な移行戦略を整理します。

E.1 「そもそも移行すべきか」のチェック

以下に Yes が 3 つ以上 ある場合のみ検討推奨:

  • [ ] モノリスの規模が 50 万行以上
  • [ ] 開発者が 50 人以上、複数チーム
  • [ ] デプロイが月 1 回以下になっている
  • [ ] 機能ごとに負荷特性が大きく異なる
  • [ ] 技術を部分的に刷新したい
  • [ ] チーム間のデプロイ衝突が頻発

これらがないなら モジュラモノリスで十分 かもしれません。

E.2 Strangler Fig パターン(Martin Fowler)

イチジクの絞め殺し植物のように、新しいサービスが徐々にモノリスを包んでいく パターン。

【図26】Strangler Fig パターン:

graph TD Client[クライアント] Proxy[Proxy Gateway] Monolith[モノリス 旧] NewSvc1[新サービス 1] NewSvc2[新サービス 2] Client --> Proxy Proxy --> Monolith Proxy --> NewSvc1 Proxy --> NewSvc2

段階:

  1. Proxy を導入:全リクエストを Proxy 経由にする
  2. 1 機能を切り出す:新サービス化、Proxy でルート変更
  3. 繰り返す:機能ごとに移行
  4. 最後にモノリス廃止

E.3 移行順序の決め方

優先度高:

  • 独立性が高い:他機能との結合が少ない
  • 変更頻度が高い:切り出すメリット大
  • 負荷特性が特殊:独立スケールしたい
  • 技術刷新したい:他言語・他 DB にしたい

後回し:

  • コアドメイン(複雑すぎる)
  • 多数の機能から参照される共通機能
  • レガシー DB に依存

E.4 データ移行の戦略

  1. 共有 DB を維持しつつコードだけ分離(最初のステップ)
  2. DB テーブル単位でデータオーナーを決める
  3. 読み取りはレプリケーション or API
  4. 書き込みは二重書き込み(Dual Write)で移行
  5. 最終的に別 DB に分離

E.5 よくある失敗

  • 先にマイクロサービス化してからドメイン整理 ← 逆
  • Distributed Monolith 化(デプロイが同時)
  • 観測性なしで移行(障害時の原因不明)
  • 組織が従来のまま(Conway の法則で失敗)
  • 移行途中で放棄(一番悪い状態)

E.6 成功事例

  • Amazon:2000 年代初頭に大規模マイクロサービス化
  • Netflix:2008 年の DB 障害を機に移行
  • Uber:2013-2017 年に大量マイクロサービス化(ただし逆戻りも多い)

注意: Amazon Prime Video が 2023 年にマイクロサービスを分散モノリスに戻して 90% コスト削減。「常に正解」はない。


附録F:Architecture Decision Record (ADR)

初心者向けメモ: アーキテクチャ判断は忘れられやすい。「なぜこの選択をしたか」を記録する軽量ドキュメント形式が ADR です。docs/adr/ に Markdown ファイルとして Git で管理します。

F.1 ADR テンプレート(Michael Nygard 式)

# ADR-001: リードモデルに Redis を採用

## ステータス
採用(2026-04-24)

## 背景
注文履歴の参照クエリが遅く、DB 負荷が高い。レスポンスタイム P99 で 2 秒超。
キャンペーン時にさらに悪化する。

## 決定
リードモデルを Redis に格納し、書き込み時に更新する。

## 選択肢

### 選択肢 1:Redis キャッシュ
- Pros: 高速、シンプル、運用慣れている
- Cons: メモリコスト、永続化は別途

### 選択肢 2:Elasticsearch
- Pros: 検索機能豊富
- Cons: オーバースペック、学習コスト

### 選択肢 3:リードレプリカ追加
- Pros: 既存構成の延長
- Cons: 根本的遅さは変わらない

## 結果
- 採用:選択肢 1(Redis)
- 期待効果:レスポンスタイム P99 を 200ms 以下に
- 副作用:データ整合性は結果整合
- リスク:Redis ダウン時のフォールバック設計必要

## 関連
- ADR-002: Cache-Aside パターンの採用
- GitHub Issue #123

F.2 ツール

  • adr-tools:CLI で管理
  • Log4brains:Web UI
  • ADR Manager(VS Code extension)
  • 単純に Markdown でも十分

F.3 いつ書くか

  • 重要な技術選定(言語、フレームワーク、DB)
  • アーキテクチャパターン採用(CQRS、マイクロサービス化)
  • 可逆でない判断
  • チーム内で議論が分かれた判断

附録G:よくある質問(FAQ)

G.1 「モノリスとマイクロサービス、最初どちらで始めるべき?」

A:モノリスから始めよ。 Martin Fowler の “Monolith First” 原則。最初からマイクロサービスで始めると、ドメイン境界が不明確なまま分割して後で痛い目を見る。

G.2 「Clean Architecture は必須?」

A:規模次第。 小規模なら過剰。中〜大規模、長期運用、複雑ドメインなら強く推奨。

G.3 「REST か GraphQL か gRPC か?」

A:

  • 公開 API・多様なクライアント:REST
  • モバイル・複雑な取得要件:GraphQL
  • 内部マイクロサービス・高速通信:gRPC
  • 混在も普通(外部 REST、内部 gRPC)

G.4 「SQL か NoSQL か?」

A:デフォルトは SQL。 強い整合性、JOIN、成熟したエコシステム。NoSQL は「明確な理由がある時」に選ぶ:

  • 超大規模書き込み → Cassandra
  • 柔軟スキーマ → MongoDB
  • グラフ関係 → Neo4j
  • キャッシュ → Redis

G.5 「Kubernetes は必須?」

A:規模次第。 小規模なら Cloud Run、ECS、Heroku で十分。大規模・複雑なら K8s の恩恵大。

G.6 「アーキテクト は必要?」

A:中規模以上で有益。 ただし「タワーから命令する」のではなく、「開発チームと一緒にコード書くアーキテクト」が理想。

G.7 「新技術はどれくらい採用すべき?」

A:Gartner Hype Cycle を意識する。

  • Innovation Trigger:遊び程度
  • Peak of Inflated Expectations:避ける(誇張)
  • Trough of Disillusionment:学習の好機
  • Slope of Enlightenment:本番採用検討
  • Plateau of Productivity:安心して導入

G.8 「AI 時代、アーキテクチャの価値は?」

A:むしろ上がる。 コード生成は AI ができるが、「どう構造化するか」「何を分けるか」「どうトレードオフを評価するか」は人間の判断。AI 時代、アーキテクトの価値は増すと予測される。

まとめ

アプリケーションアーキテクチャは、変更に強い構造をどう作るかを考える章です。モノリス、マイクロサービス、API、データ、観測性、運用までをまとめて見ることで、設計判断の軸が整理できます。