ストーリー
佐藤CTOが渋い顔で言いました。
ADRとは
概要
| 項目 | 内容 |
|---|---|
| 定義 | アーキテクチャに関する重要な意思決定を記録する短いドキュメント |
| 目的 | 「なぜその決定をしたか」を将来の自分とチームのために残す |
| 特徴 | 軽量、イミュータブル(一度書いたら変更しない)、コードと一緒に管理 |
| 提唱者 | Michael Nygard(2011年) |
ADRの価値
ADRがない組織:
- 「なぜこう設計したの?」→ 誰も知らない
- 「この技術を変えていい?」→ 変更の影響がわからない
- 新メンバー「なぜこの構成に?」→ 説明に毎回1時間
ADRがある組織:
- 「なぜこう設計したの?」→ ADR-005 を読んで
- 「この技術を変えていい?」→ ADR-005 の前提条件が変わったか確認しよう
- 新メンバー「なぜこの構成に?」→ docs/adr/ を読めば経緯がわかる
ADRテンプレート(基本形)
Michael Nygard の原型
# ADR-NNN: [タイトル]
## ステータス
[Proposed | Accepted | Deprecated | Superseded by ADR-XXX]
## コンテキスト
[この決定が必要になった背景と制約条件]
## 決定
[何を決定したか]
## 結果
[この決定によって生じるポジティブ・ネガティブな影響]
「このシンプルさがADRの最大の強みだ。書くのに30分以上かかるなら、それはADRではなく設計書だ」 — 佐藤CTO
MADR(Markdown Any Decision Records)フォーマット
より構造化されたフォーマットで、チームでの議論を促進します。
# ADR-NNN: [タイトル]
## ステータス
Accepted
## コンテキスト
### 問題
[解決すべき問題の説明]
### 決定要因
- [要因1: 例えばパフォーマンス要件]
- [要因2: 例えばチームのスキルセット]
- [要因3: 例えばコスト制約]
## 検討した選択肢
### 選択肢1: [名前]
- 良い点: [メリット]
- 悪い点: [デメリット]
### 選択肢2: [名前]
- 良い点: [メリット]
- 悪い点: [デメリット]
### 選択肢3: [名前]
- 良い点: [メリット]
- 悪い点: [デメリット]
## 決定
[選択肢Xを採用する]
### 理由
[なぜその選択肢を選んだか]
## 結果
### ポジティブ
- [良い影響]
### ネガティブ
- [悪い影響・トレードオフ]
### リスク
- [残存リスクと緩和策]
ADRの実例
例: データベース選定
# ADR-005: 患者データストアとしてPostgreSQLを採用する
## ステータス
Accepted (2026-01-15)
## コンテキスト
### 問題
患者管理システムのデータストアを選定する必要がある。
現在MongoDBを使用しているが、以下の課題がある:
- トランザクション処理の信頼性に不安
- リレーショナルデータの結合が複雑
- SOC 2 監査でスキーマ管理の不備を指摘された
### 決定要因
- 医療データのACID準拠トランザクション
- SOC 2 / HIPAA のコンプライアンス要件
- チームのスキルセット(SQL経験者15名中12名)
- 既存データの移行コスト
## 検討した選択肢
### 選択肢1: PostgreSQL
- 良い点: ACID完全準拠、豊富なデータ型、JSON対応、チームに経験者多数
- 悪い点: 水平スケーリングが複雑
### 選択肢2: MongoDB(現行維持)
- 良い点: 移行コストゼロ、スキーマの柔軟性
- 悪い点: マルチドキュメントトランザクションの制限、監査指摘への対応が必要
### 選択肢3: CockroachDB
- 良い点: 分散SQL、水平スケーリング、PostgreSQL互換
- 悪い点: 運用経験なし、コストが高い、学習コスト大
## 決定
PostgreSQL を採用する。
### 理由
1. 医療データには厳格なACIDトランザクションが必須
2. SOC 2 監査要件への対応が容易(スキーマ管理、アクセス制御)
3. チームの75%がSQL経験者であり、学習コストが最小
4. RDS PostgreSQL により運用負荷を軽減可能
## 結果
### ポジティブ
- トランザクションの信頼性が向上する
- SOC 2 監査への対応が容易になる
- チームの既存スキルを活用できる
### ネガティブ
- MongoDBからのデータ移行コスト(推定3人月)
- 一部のドキュメント指向クエリの書き換えが必要
### リスク
- 将来の水平スケーリング需要に対しては、
Read Replica + パーティショニングで対応予定
- リスク軽減: 半年後にトラフィック分析を実施し、
スケーリング戦略を再評価する(→ ADR-010予定)
ADR運用の実践
ディレクトリ構造
project-root/
├── docs/
│ └── adr/
│ ├── 0001-use-postgresql-for-patient-data.md
│ ├── 0002-adopt-event-driven-architecture.md
│ ├── 0003-choose-nestjs-for-backend.md
│ ├── 0004-implement-cqrs-for-reporting.md
│ └── template.md
├── src/
└── ...
ライフサイクル
Proposed → Accepted → [Active]
↓
Deprecated(もう従わない)
or
Superseded by ADR-XXX(新しい決定に置き換え)
TypeScript でのADR管理ツール例
// adr-tool.ts - ADR管理CLI
interface ADR {
id: number;
title: string;
status: 'Proposed' | 'Accepted' | 'Deprecated' | 'Superseded';
date: string;
supersededBy?: number;
deciders: string[];
tags: string[];
}
// ADR一覧の生成
function generateADRIndex(adrs: ADR[]): string {
const rows = adrs.map(adr => {
const status = adr.supersededBy
? `Superseded by [ADR-${adr.supersededBy}]`
: adr.status;
return `| ${adr.id} | ${adr.title} | ${status} | ${adr.date} |`;
});
return [
'# Architecture Decision Records',
'',
'| ID | Title | Status | Date |',
'|----|-------|--------|------|',
...rows,
].join('\n');
}
// 新規ADR作成
function createADR(title: string, template: string): string {
const nextId = getNextADRId();
const filename = `${String(nextId).padStart(4, '0')}-${slugify(title)}.md`;
const content = template
.replace('ADR-NNN', `ADR-${nextId}`)
.replace('[タイトル]', title)
.replace('[date]', new Date().toISOString().split('T')[0]);
return filename;
}
Lightweight ADR Process
lightweight_adr_process:
when_to_write:
- "新しい技術やフレームワークの採用"
- "アーキテクチャパターンの変更"
- "インフラ構成の重要な変更"
- "APIの破壊的変更"
- "セキュリティに関する決定"
when_not_to_write:
- "小さなライブラリの追加"
- "コーディングスタイルの変更"
- "バグ修正の方法"
process:
step1: "PRにADRファイルを含める"
step2: "チームレビュー(通常のコードレビューと同時)"
step3: "合意が取れたらマージ(= Accepted)"
step4: "決定を変更する場合は新しいADRを作成(元のADRはSuperseded)"
time_budget: "1つのADR作成に30分以内"
Decision Log(意思決定ログ)
ADRの上位レベル管理
decision_log:
purpose: "全ADRを俯瞰し、技術戦略の一貫性を確認する"
format:
columns:
- "ADR ID"
- "カテゴリ(データ/インフラ/API/セキュリティ)"
- "影響範囲(単一サービス/複数サービス/全体)"
- "ステータス"
- "関連ADR"
review_cadence: "四半期ごとにアーキテクチャレビューで棚卸し"
actions:
- "前提条件が変わったADRを特定しDeprecated/Supersededにする"
- "新たな決定が必要な領域を洗い出す"
- "ADR間の整合性を確認する"
| ADR ID | カテゴリ | タイトル | 影響範囲 | ステータス |
|---|---|---|---|---|
| 001 | データ | PostgreSQL採用 | 全サービス | Accepted |
| 002 | アーキテクチャ | イベント駆動採用 | 複数サービス | Accepted |
| 003 | フレームワーク | NestJS採用 | バックエンド | Accepted |
| 004 | アーキテクチャ | CQRS導入 | レポーティング | Proposed |
| 005 | インフラ | EKS移行 | 全サービス | Accepted |
まとめ
| ポイント | 内容 |
|---|---|
| ADRの目的 | 「なぜその決定をしたか」を記録し、知識の喪失を防ぐ |
| テンプレート | コンテキスト→検討した選択肢→決定→結果の構造 |
| MADR | 選択肢の比較を構造化した拡張フォーマット |
| 運用 | コードと一緒にGit管理、PRレビューで承認 |
チェックリスト
- ADRの目的と価値を理解した
- 基本テンプレートとMADRフォーマットを把握した
- ADRを書くべき場面と書かなくてよい場面を理解した
- Lightweight ADR Processの運用方法を把握した
次のステップへ
次は「アーキテクチャレビュープロセス」を学びます。ADRで記録した意思決定が、組織全体でどのようにレビュー・承認されるかを見ていきましょう。
推定読了時間: 40分