Architecture Decision Records (ADRs)
WHAT
Lightweight documentation capturing the context, decision, and consequences of significant technical choices. ADRs become the institutional memory of why things are built the way they are.
WHEN
- - Adopting new frameworks or technologies
- Choosing between architectural approaches
- Making database or infrastructure decisions
- Defining API design patterns
- Any decision that would be hard to reverse or understand later
KEYWORDS
ADR, architecture decision record, technical documentation, decision log, MADR, RFC, design decisions, trade-offs
Quick Decision: Should I Write an ADR?
| Write ADR | Skip ADR |
|---|
| New framework/language adoption | Minor version upgrades |
| Database technology choice |
Bug fixes |
| API design patterns | Implementation details |
| Security architecture | Routine maintenance |
| Integration patterns | Configuration changes |
| Breaking changes | Code formatting |
ADR Lifecycle
CODEBLOCK0
Never modify accepted ADRs - write new ones to supersede.
Templates
Template 1: Standard (Copy This)
CODEBLOCK1
Template 2: Full (For Major Decisions)
CODEBLOCK2
Template 3: Lightweight (For Smaller Decisions)
CODEBLOCK3
Template 4: Y-Statement (One-Liner)
CODEBLOCK4
Template 5: Deprecation ADR
CODEBLOCK5
Directory Structure
CODEBLOCK6
ADR Index (README.md)
CODEBLOCK7
Tooling: adr-tools
CODEBLOCK8
Review Checklist
Before submission:
- - [ ] Context clearly explains the problem
- [ ] All viable options considered
- [ ] Pros/cons balanced and honest
- [ ] Consequences documented (positive AND negative)
During review:
- - [ ] At least 2 senior engineers reviewed
- [ ] Affected teams consulted
- [ ] Security implications considered
- [ ] Reversibility assessed
After acceptance:
- - [ ] Index updated
- [ ] Team notified
- [ ] Implementation tickets created
NEVER
- - Modify accepted ADRs: Write new ones to supersede
- Skip context: Future readers need the "why"
- Hide failures: Rejected decisions are valuable learning
- Be vague: Specific decisions, specific consequences
- Forget implementation: ADR without action is waste
- Over-document: Keep to 1-2 pages max
- Document too late: Write BEFORE implementation starts
架构决策记录 (ADRs)
是什么
轻量级文档,记录重要技术决策的背景、决策和后果。ADRs 成为为什么以特定方式构建事物的机构记忆。
何时使用
- - 采用新框架或技术
- 在架构方法之间进行选择
- 做出数据库或基础设施决策
- 定义 API 设计模式
- 任何日后难以撤销或理解的决策
关键词
ADR, 架构决策记录, 技术文档, 决策日志, MADR, RFC, 设计决策, 权衡
快速决策:我应该写 ADR 吗?
| 写 ADR | 跳过 ADR |
|---|
| 新框架/语言采用 | 次要版本升级 |
| 数据库技术选择 |
错误修复 |
| API 设计模式 | 实现细节 |
| 安全架构 | 日常维护 |
| 集成模式 | 配置变更 |
| 破坏性变更 | 代码格式化 |
ADR 生命周期
提议 → 已接受 → 已弃用 → 已取代
↓
已拒绝
切勿修改已接受的 ADR - 编写新的 ADR 来取代它们。
模板
模板 1:标准版(复制此模板)
markdown
ADR-NNNN:[标题]
状态
[提议 | 已接受 | 已弃用 | 已被 ADR-XXXX 取代]
背景
[问题是什么?有哪些因素在起作用?最多 2-3 段。]
决策
我们将 [决策陈述]。
后果
正面
负面
风险
相关
模板 2:完整版(用于重大决策)
markdown
ADR-0001:使用 PostgreSQL 作为主数据库
状态
已接受
背景
我们需要为电商平台选择主数据库,该平台需处理:
- - 约 10,000 名并发用户
- 具有层级类别的复杂产品目录
- 订单和支付的事务处理
- 产品的全文搜索
团队有 MySQL、PostgreSQL 和 MongoDB 的使用经验。
决策驱动因素
- - 必须 具备支付处理的 ACID 合规性
- 必须 支持报表的复杂查询
- 应 支持全文搜索以减少基础设施
- 应 对灵活的产品属性有良好的 JSON 支持
考虑的选项
选项 1:PostgreSQL
优点:ACID 合规,出色的 JSONB 支持,内置全文搜索,PostGIS
缺点:复制比 MySQL 稍复杂
选项 2:MySQL
优点:团队熟悉,复制简单
缺点:JSON 支持较弱,无内置全文搜索
选项 3:MongoDB
优点:灵活的模式,原生 JSON
缺点:不支持多文档事务的 ACID,团队经验有限
决策
我们将使用
PostgreSQL 15 作为主数据库。
理由
PostgreSQL 在 ACID 合规性(对电商至关重要)、内置功能(减少基础设施)和团队熟悉度之间提供了最佳平衡。
后果
正面
- - 单一数据库处理事务、搜索和地理空间数据
- 降低运维复杂性
- 金融数据的强一致性
负面
- - 团队需要 PostgreSQL 专项培训
- 垂直扩展限制可能需要只读副本
风险
- - 全文搜索可能不如 Elasticsearch 扩展性好
- 缓解措施:如有需要,设计为可添加 ES
实施说明
- - 对灵活的产品属性使用 JSONB
- 使用 PgBouncer 实现连接池
- 为只读副本设置流复制
相关
- - ADR-0002:缓存策略 (Redis)
- ADR-0005:搜索架构
模板 3:轻量版(用于较小决策)
markdown
ADR-0012:前端采用 TypeScript
状态:已接受
日期:2024-01-15
决策者:@alice, @bob
背景
React 代码库有 50 多个组件,由于属性类型不匹配导致的错误不断增加。
决策
所有新的前端代码采用 TypeScript。逐步迁移现有代码。
后果
好处:在编译时捕获类型错误,更好的 IDE 支持
坏处:学习曲线,初期速度减慢
缓解措施:培训课程,allowJs: true 以逐步采用
模板 4:Y 陈述(一句话)
markdown
ADR-0015:API 网关选择
在 构建微服务架构 的背景下,
面对 需要集中式 API 管理和速率限制,
我们决定采用 Kong 网关
而不是 AWS API 网关和自定义 Nginx,
以实现 供应商独立性和插件可扩展性,
同时接受 我们需要自行管理 Kong 基础设施。
模板 5:弃用 ADR
markdown
ADR-0020:弃用 MongoDB,改用 PostgreSQL
状态
已接受(取代 ADR-0003)
背景
ADR-0003(2021 年)为用户档案选择了 MongoDB。自那以后:
- - MongoDB 事务对我们的用例仍然存在问题
- 我们的模式已经稳定,很少更改
- 维护两个数据库增加了运维负担
决策
弃用 MongoDB,将用户档案迁移到 PostgreSQL。
迁移计划
- 1. 第 1-2 周:创建 PostgreSQL 模式,启用双写
- 第 3-4 周:回填历史数据,验证一致性
- 第 5 周:将读取切换到 PostgreSQL
- 第 6 周:移除 MongoDB 写入,下线
经验教训
- - 模式灵活性的好处被高估了
- 多个数据库的运维成本被低估了
目录结构
docs/
└── adr/
├── README.md # 索引和指南
├── template.md # 团队的 ADR 模板
├── 0001-use-postgresql.md
├── 0002-caching-strategy.md
├── 0003-mongodb-user-profiles.md # [已弃用]
└── 0020-deprecate-mongodb.md # 取代 0003
ADR 索引 (README.md)
markdown
架构决策记录
| ADR | 标题 | 状态 | 日期 |
|---|
| 0001 | 使用 PostgreSQL | 已接受 | 2024-01-10 |
| 0002 |
使用 Redis 缓存 | 已接受 | 2024-01-12 |
|
0003 | MongoDB 用于用户档案 | 已弃用 | 2023-06-15 |
|
0020 | 弃用 MongoDB | 已接受 | 2024-01-15 |
创建新 ADR
- 1. 将 template.md 复制为 NNNN-title-with-dashes.md
- 填写模板,提交 PR 进行审查
- 批准后更新此索引
工具:adr-tools
bash
安装
brew install adr-tools
初始化
adr init docs/adr
创建新 ADR
adr new 使用 PostgreSQL 作为主数据库
取代一个 ADR
adr new -s 3 弃用 MongoDB,改用 PostgreSQL
生成索引
adr generate toc > docs/adr/README.md
审查清单
提交前:
- - [ ] 背景清晰解释了问题
- [ ] 考虑了所有可行的选项
- [ ] 优缺点平衡且诚实
- [ ] 记录了后果(正面和负面)
审查期间:
- - [ ] 至少 2 名高级工程师审查过
- [ ] 咨询了受影响的团队
- [ ] 考虑了安全影响
- [ ] 评估了可逆性
接受后:
- - [ ] 更新了索引
- [ ] 通知了团队
- [ ] 创建了实施工单
切勿
- - 修改已接受的 ADR:编写新的 ADR 来取代
- 跳过背景:未来的读者需要知道为什么
- 隐藏失败:被拒绝的决策是宝贵的学习经验
- 含糊不清:具体的决策,具体的后果
- 忘记实施:没有行动的 ADR 是浪费
- 过度记录:最多保持 1-2 页
- 记录太晚:在实施开始之前编写