ADR とは何か
ADR(Architecture Decision Record)は、「ある時点においてどのような設計上の判断をなぜ行ったか」を記録する軽量なドキュメントです。
1つの ADR が1つの決定を表し、リポジトリ内の docs/adr/ ディレクトリに番号付きファイルとして蓄積していきます。
ADR がない現場でよく起きる問題は「誰かがなぜこの設計にしたのか分からない」という状態です。 口頭で決まった内容は数ヶ月後に誰も覚えておらず、ドキュメントがないため再議論が発生します。 ADR はこの「設計の忘却問題」を防ぐための最も軽量な手段です。
💡 ADR の特徴
ADR は「不変の記録」です。決定を変更する場合は既存の ADR を書き換えるのではなく、新しい ADR を追加して旧 ADR を「Superseded(置換済み)」に更新します。これにより判断の変遷が追跡できます。
どのタイミングで ADR を書くか
ADR を書くべき判断の基準は「後で理由を説明できないと困るか?」です。以下のような決定は ADR 化の対象です。
| 判断の種類 | 例 |
|---|---|
| 技術スタック選定 | フレームワーク・データベース・メッセージキューの選択 |
| アーキテクチャパターン | モノリス vs マイクロサービス・レイヤー構造の採用 |
| 外部サービスの採用 | 認証に Auth0 を使う・ストレージに S3 を使う |
| 非機能要件のトレードオフ | 整合性よりスループットを優先するキャッシュ戦略 |
| コーディング規約の変更 | 例外処理方針・ログフォーマットの統一 |
| 廃止・移行の決定 | 旧ライブラリの廃止・API バージョンの削除 |
ADR の5セクション構成
Michael Nygard が提唱した元の形式にステータスと代替案を加えた5セクション構成が実務で広く使われています。
① タイトル(Title)
番号と内容を一言で表す文字列。「何を決めたか」が分かる名詞句または動詞句で書きます。 ファイル名と一致させることが推奨されます。
# ADR-0012: API ゲートウェイに Kong を採用する
② ステータス(Status)
現在の決定の状態を明示します。詳細は次のセクションで解説します。
③ コンテキスト(Context)
この決定が必要になった背景・制約・課題を記述します。「なぜこの決定が必要だったのか」が分かる情報をすべて含めます。
定義すべき内容:
| 項目 | 説明 |
|---|---|
| 背景・課題 | 何が問題で・何が変わったのか |
| 制約条件 | 予算・チームスキル・既存技術スタック・期限など |
| 関連 ADR | この決定に影響を与えた以前の決定 |
| ステークホルダー | 誰がこの決定に影響を受けるか |
④ 決定(Decision)
「何をするか」を明確に書きます。曖昧な表現は禁物——「〜を検討する」ではなく「〜を採用する」「〜を使用しない」のように断言します。 代替案をここで比較し、採用理由を論理的に説明します。
| 比較軸 | Kong | AWS API Gateway | Nginx |
|---|---|---|---|
| 認証プラグイン | 豊富(JWT/OAuth/LDAP) | Cognito 依存 | 別途実装必要 |
| レート制限 | ネイティブ対応 | ネイティブ対応 | プラグイン要 |
| オンプレ対応 | ◎ | ✗(AWS 専用) | ◎ |
| 学習コスト | 中 | 低(AWS 既知) | 低 |
⑤ 結果・影響(Consequences)
この決定を採用した場合の影響を正直に記載します。ポジティブな面だけでなく、トレードオフ・デメリット・将来リスクも含めます。
## 結果・影響
### ポジティブ
- 認証・レート制限を API ゲートウェイに集約でき、各マイクロサービスの実装が単純化される
- Kong のプラグインエコシステムにより、将来の機能追加がコードなしで可能
### ネガティブ(トレードオフ)
- Kong 自体の運用スキルが必要になる(学習コスト:2週間想定)
- Kong が SPOF(単一障害点)になるため、高可用性構成(Active-Active)が必要
### 将来への影響
- Kong のバージョンアップに追従するメンテナンスコストが発生する
- オンプレからクラウド移行時に Kong Cloud(Konnect)への移行が選択肢になる
ステータス管理
ADR のステータスは決定の生存状態を表します。以下の4種類が標準的です。
| ステータス | 意味 | 使うタイミング |
|---|---|---|
| Proposed | 提案中 | PR でレビュー中の段階 |
| Accepted | 採択済み | チームの合意が得られた |
| Superseded | 別 ADR に置換済み | 新しい ADR が同じ決定を上書きした |
| Deprecated | 廃止 | 決定の前提が崩れ無効になった |
ファイル命名・保存場所
ADR は以下のルールでリポジトリ内に保存することが一般的です。
docs/
└── adr/
├── 0001-use-postgresql-for-primary-db.md
├── 0002-adopt-layered-architecture.md
├── 0003-use-redis-for-session-cache.md
└── 0012-adopt-kong-as-api-gateway.md
ファイル名は NNNN-内容を表す-kebab-case.md の形式が標準です。番号は4桁ゼロ埋めにすることで ls の昇順ソートで時系列順に並びます。
ADR の記載例
# ADR-0012: API ゲートウェイに Kong を採用する
## ステータス
Accepted(2026-06-20)
## コンテキスト
マイクロサービス化に伴い、認証・認可・レート制限・ロギングを各サービスが
個別に実装している状態が問題になっている。重複実装の解消と横断的関心事の
集約のため、API ゲートウェイの導入を検討した。
制約:
- オンプレ環境での動作が必須(AWS 専用ソリューションは対象外)
- チームに Nginx の運用経験あり(Kong は未経験)
- 導入まで 3 ヶ月以内
## 決定
API ゲートウェイとして **Kong(オープンソース版)** を採用する。
### 比較した代替案
| 観点 | Kong | AWS API Gateway | Nginx + Lua |
|---|---|---|---|
| オンプレ対応 | ◎ | ✗ | ◎ |
| 認証プラグイン | 豊富 | Cognito 依存 | 自前実装 |
| レート制限 | ネイティブ | ネイティブ | プラグイン要 |
| 学習コスト | 中 | 低 | 高 |
Kong を選定した理由:オンプレ必須という制約を満たしつつ、
プラグインで認証・レート制限を設定のみで実現できるため。
## 結果・影響
### ポジティブ
- 横断的関心事を API ゲートウェイに集約し、各サービスの実装が単純化される
- プラグインによる将来の機能追加がコード変更なしで可能
### ネガティブ(トレードオフ)
- Kong 自体の運用知識が必要(習得コスト 2 週間を見込む)
- 高可用性のための Active-Active 構成が追加インフラコストになる
## 関連 ADR
- ADR-0003: Redis をセッションキャッシュに採用する(セッション管理との連携に影響)
Python で ADR を自動管理する
ADR が増えてくると一覧性が重要になります。Python で ADR ファイルを解析してステータス別一覧を生成するスクリプトを紹介します。
① ADR 一覧を Markdown テーブルで出力
"""
docs/adr/ 配下の Markdown ADR を解析し、
ステータス別の一覧表を標準出力に書き出す。
"""
import re
from pathlib import Path
from collections import defaultdict
ADR_DIR = Path("docs/adr")
STATUS_PATTERN = re.compile(
r"##\s+ステータス\s*\n(.+?)(?:\n##|\Z)",
re.DOTALL | re.IGNORECASE
)
TITLE_PATTERN = re.compile(r"^#\s+(.+)", re.MULTILINE)
def parse_adr(path: Path) -> dict:
text = path.read_text(encoding="utf-8")
title_m = TITLE_PATTERN.search(text)
title = title_m.group(1).strip() if title_m else path.stem
status_m = STATUS_PATTERN.search(text)
status_raw = status_m.group(1).strip() if status_m else "Unknown"
# 日付部分を除いてステータス名だけ取り出す
status = re.split(r"[((]", status_raw)[0].strip()
return {
"file": path.name,
"title": title,
"status": status,
}
def main():
if not ADR_DIR.exists():
print(f"ディレクトリが見つかりません: {ADR_DIR}")
return
adrs = sorted(
[parse_adr(p) for p in ADR_DIR.glob("*.md")],
key=lambda x: x["file"]
)
by_status = defaultdict(list)
for adr in adrs:
by_status[adr["status"]].append(adr)
print("# ADR 一覧\n")
for status, items in sorted(by_status.items()):
print(f"## {status}\n")
print("| ファイル | タイトル |")
print("|---|---|")
for item in items:
print(f"| `{item['file']}` | {item['title']} |")
print()
if __name__ == "__main__":
main()
② 次の ADR 番号を自動採番
"""
既存の ADR から次番号を自動採番し、テンプレートファイルを生成する。
使い方: python new_adr.py "API ゲートウェイに Kong を採用する"
"""
import sys
import re
from pathlib import Path
from datetime import date
ADR_DIR = Path("docs/adr")
TEMPLATE = """\
# ADR-{num:04d}: {title}
## ステータス
Proposed({date})
## コンテキスト
## 決定
## 結果・影響
### ポジティブ
-
### ネガティブ(トレードオフ)
-
## 関連 ADR
-
"""
def next_number() -> int:
existing = list(ADR_DIR.glob("*.md"))
if not existing:
return 1
nums = []
for p in existing:
m = re.match(r"^(\d+)", p.name)
if m:
nums.append(int(m.group(1)))
return max(nums) + 1 if nums else 1
def main():
if len(sys.argv) < 2:
print("使い方: python new_adr.py '決定内容のタイトル'")
sys.exit(1)
title = sys.argv[1]
num = next_number()
slug = re.sub(r"[^\w\s-]", "", title.lower()).replace(" ", "-")
filename = f"{num:04d}-{slug}.md"
path = ADR_DIR / filename
ADR_DIR.mkdir(parents=True, exist_ok=True)
path.write_text(
TEMPLATE.format(num=num, title=title, date=date.today().isoformat()),
encoding="utf-8"
)
print(f"作成しました: {path}")
if __name__ == "__main__":
main()
ADR のアンチパターン
| アンチパターン | 問題 | 対策 |
|---|---|---|
| 後から書く | 決定の背景が曖昧になる | 決定直後・PR 時に書くルールにする |
| 既存 ADR を書き換える | 判断の変遷が追跡できなくなる | 新 ADR を追加し旧 ADR を Superseded にする |
| 結果・影響を書かない | トレードオフが伝わらない | ネガティブ面も正直に記述する |
| 小さすぎる決定まで書く | ADR が増えすぎて誰も読まなくなる | 「後で理由を説明できないと困るか?」で取捨選択 |
| ADR を Wiki に置く | コードとドキュメントが同期しない | リポジトリ内の docs/adr/ に置く |
まとめ
✅ ADR で定義すべき5要素
□ タイトル — 番号 + 何を決めたかを一言で
□ ステータス — Proposed / Accepted / Superseded / Deprecated
□ コンテキスト — 背景・制約・関連 ADR
□ 決定 — 何をするか・代替案との比較・採用理由
□ 結果・影響 — ポジティブ面とネガティブ面(トレードオフ)を正直に記述
ADR の最大の価値は「なぜそうしたか」を未来の自分やチームメンバーが即座に理解できる点にあります。 Python スクリプトで一覧化・自動採番を仕組み化し、PR テンプレートに「ADR が必要な変更か確認」のチェック項目を加えると、継続して書き続ける文化が育ちます。