Written by
Halkwinds Editorial Team
Halkwinds Research & Editorial

Architecture Decision Records: The Engineering Practice That Prevents Repeated Mistakes
How to write lightweight ADRs that capture context, trade-offs, and consequences — and integrate them into an engineering culture.
Six months into a project, a new engineer asks the question that makes senior developers wince: "Why are we using DynamoDB here instead of Postgres?" Nobody remembers. The person who made the decision left the company. The Slack thread is buried. The trade-offs that felt obvious in the moment have evaporated, and now the team spends a week debating a decision that was already settled — or worse, quietly reverses it and re-introduces the exact problem the original choice solved. This is the tax that undocumented architecture decisions levy on every growing engineering organization. Architecture Decision Records (ADRs) are the cheapest, most durable way to stop paying it.
- Background / Why This Matters
- Core Concepts and Architecture
- Implementation Strategy
- Scaling and Operational Considerations
- Common Mistakes / What to Avoid
- Frequently Asked Questions
- Conclusion
Background / Why This Matters
Architecture decisions are the choices with long shadows — the ones that are expensive or painful to reverse later. Choosing a message queue, committing to a monolith versus microservices, picking an auth strategy, deciding how you handle multi-tenancy. These decisions shape everything downstream, yet in most teams they live in three unreliable places: someone's memory, a scattered set of Slack messages, and the code itself.
The problem is that code shows you what was decided but never why. When a reviewer sees an eventual-consistency pattern in the codebase, they can't tell whether it was a deliberate trade-off or an accident someone forgot to fix. That ambiguity produces two failure modes engineering managers know well:
- Repeated debates. The same architectural questions resurface every few months because no one recorded the resolution.
- Reversed decisions with lost context. A team unknowingly undoes a hard-won trade-off, only to rediscover the original constraint the hard way.
Michael Nygard introduced the modern ADR format in 2011, and it has since become a widely adopted lightweight practice precisely because it addresses these failure modes without heavyweight documentation overhead. The core insight is that the context and consequences of a decision are more valuable than the decision itself. An ADR captures the reasoning at the moment it was freshest — before hindsight distorts it.
Actionable takeaway: Before your next big technical debate, ask "Have we made this decision before?" If the answer requires archaeology through Slack, you have an ADR-shaped hole in your process.
Core Concepts and Architecture
An architecture decision record is a short, immutable document that captures a single architecturally significant decision, its context, and its consequences. The keyword is immutable: you don't edit an old ADR when you change your mind. You write a new one that supersedes it. This creates a decision log — a chronological, append-only history that reads like git for your architecture.
The anatomy of an ADR
A good ADR is short enough to read in two minutes. The canonical structure has just a few fields:
- Title: A short noun phrase with a sequential number, e.g. ADR-014: Use PostgreSQL row-level security for tenant isolation.
- Status: Proposed, Accepted, Deprecated, or Superseded (with a link to the successor).
- Context: The forces at play — technical constraints, business pressures, team skills, deadlines. This is the section that ages best.
- Decision: What you decided, stated plainly in active voice ("We will…").
- Consequences: What becomes easier and harder as a result. Honest ADRs list the downsides.
What counts as "architecturally significant"?
Not every decision deserves an ADR. Choosing tabs versus spaces does not; that belongs in a linter config. A useful heuristic: write an ADR when the decision is costly to reverse, affects multiple teams or services, or establishes a pattern others will copy. Examples include selecting a primary datastore, defining an API versioning strategy, adopting a new observability stack, or standardizing on an authentication provider.
How ADRs compare to other documentation
| Artifact | Answers | Lifespan | Best for |
|---|---|---|---|
| ADR | Why a decision was made | Permanent (immutable log) | Significant, hard-to-reverse choices |
| README | How to run/use this thing | Living (edited constantly) | Onboarding and operations |
| RFC / Design Doc | Detailed proposal before deciding | Snapshot in time | Large, cross-team designs pre-decision |
| Wiki page | General knowledge | Drifts stale quickly | Loose reference material |
RFCs and ADRs are complementary: an RFC is the debate, an ADR is the verdict. Many teams write an RFC for a big proposal and then distill the outcome into an ADR.
Actionable takeaway: Adopt the five-field Nygard format as-is. Resist the temptation to add sections. The friction of a bloated template is the number-one reason ADR practices die.
Implementation Strategy
The most important implementation principle is that ADRs live in the repository, in version control, next to the code they describe. Convention is a docs/adr/ or docs/decisions/ directory containing numbered Markdown files: 0001-record-architecture-decisions.md, 0002-use-postgresql.md, and so on. This keeps decisions reviewable through the same pull request workflow the team already uses.
Tooling that keeps friction low
- adr-tools — Nathan Toubro's shell scripts (the widely used
adr-toolspackage) let you runadr new "Use PostgreSQL"to scaffold a numbered file with the correct template and timestamp. - Log4brains — generates a searchable static site from your Markdown ADRs, useful when the log grows past a few dozen entries.
- Markdown + Git — honestly, this is enough for most teams. Plain files, reviewed in GitHub or GitLab pull requests, rendered natively in the repo browser.
Integrating ADRs into the workflow
Tooling is the easy part; the process is what makes ADRs stick. A practical rollout:
- Write ADR-0001 first. The very first ADR should record the decision to use ADRs. It's a small ritual that signals the practice is real.
- Trigger ADRs from pull requests. Add a checkbox to your PR template: "Does this change include an architecturally significant decision? If so, link the ADR." This puts the prompt where the work happens.
- Review ADRs like code. An ADR PR gets comments, approvals, and a merge. The Proposed status covers the review window; merging flips it to Accepted.
- Link ADRs from code and tickets. A comment in the code —
// tenant isolation approach, see ADR-014— turns the log into a navigable web rather than a graveyard.
For teams building complex systems from scratch — new cloud infrastructure, AI/ML pipelines, or greenfield platforms — establishing this discipline early pays compounding dividends. When Halkwinds designs and builds custom applications for clients, we treat the ADR log as a first-class deliverable, so the team inheriting the system understands not just what was built but the reasoning behind every load-bearing choice.
Actionable takeaway: Ship your first three ADRs this week — one retroactive (documenting a decision already made), one for something you're deciding now, and ADR-0001 itself. Momentum matters more than completeness.
Scaling and Operational Considerations
ADRs behave differently at 5 engineers versus 150. In a small team, a single docs/adr directory in the main repo is perfect. As you scale, the practice needs deliberate structure.
Distributing ADRs across services
In a microservices or multi-repo world, you face a choice: keep ADRs local to each service, or centralize them. The pragmatic answer is both. Service-specific decisions (how this service handles retries) belong in the service repo. Cross-cutting decisions (the org-wide observability standard, the shared auth model) belong in a central architecture repo that all teams can reference. Log4brains and similar tools can aggregate multiple sources into one searchable index.
Discoverability and search
A log of 200 ADRs is useless if nobody can find the relevant one. As the count grows, invest in:
- A generated, searchable static site (Log4brains, MkDocs, or Backstage's TechDocs).
- Consistent tagging — datastore, security, frontend — so engineers can filter by domain.
- An index README that groups accepted decisions by area.
Superseding and lifecycle
Decisions expire. When you migrate off a technology, don't delete the old ADR — mark it Superseded by ADR-087 and let the new record link back. This preserves the story of why the original decision no longer holds, which is exactly the context future engineers need. Estimates vary, but teams that maintain this lifecycle discipline tend to report far fewer "why did we build it this way" investigations during audits and re-platforming projects.
Cultural scaling
The hardest scaling problem is cultural, not technical. ADRs only survive if leadership visibly uses them. When an engineering manager responds to a design question with "check ADR-032," they reinforce the practice. When decisions are made in private meetings and never recorded, the log withers. Assign a rotating architecture steward per team who ensures significant decisions get captured.
Actionable takeaway: Add an "ADRs referenced" line to your architecture review meetings. If a meeting resolves an architectural question and produces no ADR, that's a process miss to correct.
Common Mistakes / What to Avoid
Most ADR failures follow predictable patterns. Avoid these:
- Making the template too heavy. If your ADR template has twelve
Explore Further