You know that feeling when you join a new project, look at the code, and silently ask yourself: "Who on earth thought it was a good idea to use this library / database / pattern here?" You ask teammates. One doesn't remember, another says "it was like that already," and the third — who actually made that call — left the company six months ago. This problem (and a few others) is solved by the ADR + ADL duo.
Quick Start: What Is What?
- ADR (Architecture Decision Record) — a single document (usually one Markdown file) that describes one specific, important technical decision. It contains context (why there was a problem), the chosen solution, and — crucially — consequences of that decision (both good and bad).
- ADL (Architecture Decision Log) — the registry, table of contents, or journal of all decisions made. Often a README.md in the ADR folder that links to individual records and shows their current status.
Why Bother at All?
- End architectural amnesia — In six months you won't remember why you chose PostgreSQL over MongoDB, or why you went with RabbitMQ instead of Kafka. ADR is your insurance policy for questions from the business or a new tech lead.
- Lightning-fast onboarding — A new developer instead of grilling seniors gets a link to /docs/adr. Reading the decision history, they understand the architectural backbone of the system in a single day.
- End endless debates — If a decision is written down and accepted, the topic is closed. Want to change something? Create a new ADR that supersedes the previous one.
- Shared ownership — Writing an ADR forces the team to think through consequences. This is not a decision made impulsively on Slack — it is a deliberate choice the whole team signs off on.
The Sacred Rule: History Is Immutable
This is the absolute foundation of working with ADR and ADL: both individual decision records and the log itself are essentially immutable — append-only.
Never rewrite history. If after a year you migrate from PostgreSQL to DynamoDB, do NOT edit the old 0002-use-postgresql.md as if Postgres was never there. The old document stays untouched — you only change its status to Superseded and add a link to the new file (e.g. 0012-migrate-to-dynamodb.md).
Record failures and rejected ideas too. Did a week-long PoC prove that a technology is completely unsuitable? Write an ADR and mark it Rejected. Describe exactly why the idea failed. In six months, when someone (or a new hire) comes up with the same "brilliant" idea, send them the link — no repeated week of the same experiments.
Where to Store ADRs? (Spoiler: As Close to Code as Possible)
Forget Confluence, SharePoints, and other external wikis. They die quickly because nobody wants to go there and update docs. The best place for ADRs is the code repository (Git).
- Versioning — you see the full history of changes to each decision.
- Pull Requests — a new ADR goes through the standard Code Review process. The team can comment on the architecture directly in the Markdown lines.
- Proximity to code — you write code and the documentation sits right next to it in /docs/adr/. No context-switching to the browser.
Tools That Make Life Easier
Classic, brilliant command-line tool. Quickly generates new ADRs from a template, automatically numbering them (e.g. 0001-use-postgresql.md) and updating statuses.
Manages ADRs in your project folder and generates a clean static website from them — useful for sharing the decision history with managers or external stakeholders.
Plain editor with Markdown preview support. More than enough to get started — no extra tooling required.
Practical Example: Templates and Structure
A typical folder layout inside your repository:
- docs/adr/README.md — the ADL (Decision Log): table of all decisions with ID, date, title, status, and links.
- 0001-record-architecture-decisions.md — the very first ADR: why you're introducing ADRs at all.
- 0002-use-postgresql-for-transactional-data.md — an example domain decision with context, options, rationale, and consequences.
The classic Nygard ADR template contains five sections: Title, Status, Context (why there was a problem), Decision (what you chose), and Consequences (positive and negative outcomes). That's it — no lengthy Word documents.
ADR Statuses Explained
- Proposed — decision under discussion (open PR / Draft).
- Accepted — decision approved and implemented.
- Rejected — idea discarded after analysis. Stays in the log for documentation purposes.
- Superseded — decision no longer current, replaced by a newer ADR (with a link).
How to Start: A Short Cheat Sheet
- Create a docs/adr folder in your project.
- Copy in the Nygard template.
- Propose the first ADR (e.g. about the linter you use or the directory architecture).
- Show it at the next sprint planning or retro and open a PR. You'll see how quickly the team grasps that this makes architectural debate easier, not harder.
References
- Michael Nygard — "Documenting Architecture Decisions" (2011), the original article that started it all
- Martin Fowler — "Architecture Decision Record" (bliki)
- Joel Spolsky — "Painless Functional Specifications" (2000): why technical documentation matters
- joelparkerhenderson/architecture-decision-record — templates, examples, and CLI tools on GitHub
- Architectural Drivers — the source of requirements that ADRs document (Digital Tech Garden)
