Most teams I’ve worked with fall into one of two camps when it comes to documenting architectural decisions: they either don’t do it at all, or they have a heavyweight process that everyone quietly ignores.
The first camp discovers the problem six months later when someone asks “why did we choose Postgres over SQL Server?” and the only person who remembers has since left. The second camp has a wiki full of half-finished documents that were painful to write and are now out of date.
Architecture Decision Records (ADRs) are meant to solve this. The concept was introduced by Michael Nygard in a blog post back in 2011, and the idea is simple: every significant technical decision gets a short document explaining what was decided and why. But like most good ideas in software, the value is in the execution.
I’ve spent the past year working on a large infrastructure migration involving dozens of decisions - networking topology, security boundaries, deployment strategies, compliance trade-offs. We used ADRs extensively, and I’ve come away with some opinions about what makes them actually useful versus what makes them another form of documentation theatre.
What ADRs are for
An ADR isn’t a design document. It’s not a specification. It’s a record of a decision - a fork in the road where you went left instead of right, and why.
The audience isn’t the person making the decision (they already know why). The audience is:
- Future you, six months from now, when you’ve forgotten the constraints that made Option B seem obviously wrong
- New team members, who need context without archaeology
- Auditors and compliance reviewers, who want to see evidence of deliberate decision-making
- The person who wants to revisit the decision, so they can understand what’s changed since it was made
That last one is important. ADRs aren’t meant to shut down debate - they’re meant to make debate productive. If someone wants to switch from Kubernetes to ECS, the ADR doesn’t say “no, we decided”; it says “here’s what we knew at the time, here’s what we optimised for, here’s what we traded off.” Now the conversation can focus on what’s changed rather than relitigating the original decision from scratch.
A template that actually gets used
The templates I’ve seen fail tend to have twenty fields, half of which are “N/A” for any given decision. The ones that work are short enough that writing one doesn’t feel like a chore.
Here’s the structure I’ve landed on:
| Section | Purpose |
|---|---|
| Status | Proposed → Accepted → Implemented (or Superseded) |
| Date | When the decision was made |
| Deciders | Who made the call (specific names) |
| Consulted/Informed | Who provided input or was notified |
| Context | The problem that required a decision |
| Decision | What we’re doing |
| Reasoning | Why this option, specifically |
| Consequences | What we gain and what we lose |
| Alternatives | What we considered and rejected |
That’s it. No “assumptions” section that nobody fills in. No “risks” section that duplicates “consequences”. No “stakeholders” matrix.
A few notes on the sections that matter most:
Status tracks the decision lifecycle. The typical progression is:
- Proposed - Under discussion, not yet agreed
- Accepted - Decision made, implementation pending
- Implemented - Decision has been acted on
- Superseded - Replaced by a later decision (link to the new ADR)
- Deprecated - No longer relevant but kept for historical context
Some teams add “Rejected” for proposals that were considered but declined. The key is that status changes are append-only - you don’t delete or edit old ADRs, you supersede them. This preserves the decision history and lets you trace how thinking evolved.
Alternatives is the most important section. It’s easy to write “we chose X” and justify it in isolation. It’s harder - and more valuable - to write “we considered X, Y, and Z, and here’s why we rejected Y and Z.” This forces you to prove you actually evaluated options rather than just going with the first thing that came to mind. It also helps future readers understand the decision space, not just the outcome.
Reasoning needs specifics, not vibes. “This approach is more scalable” is not a reason. “This approach supports horizontal scaling via read replicas, which we expect to need when we exceed 10,000 concurrent users based on current growth projections” is a reason. Numbers, constraints, references - these are what make an ADR useful rather than just a dressed-up opinion.
Consequences must include negatives. Every decision has trade-offs. If your “Consequences” section is all upside, you’re either not being honest or you haven’t thought hard enough. Documenting the downsides isn’t pessimism; it’s giving future readers the information they need to judge whether those trade-offs still make sense.
Deciders means deciders, not attendees. Use specific names, not team names. “Platform Team” tells you nothing six months later when half the team has rotated. “Sarah Chen” tells you exactly who to ask. The same applies to Consulted/Informed - “Marcus Webb, James Liu” is more useful than “Data Engineering” when you need to understand who provided input. But be honest about the Deciders list - putting six names there when really one person made the call and five were in the room dilutes accountability. The point is to know who owned the decision, not to spread responsibility so thin that nobody owns it.
ADRs are not a blame tool. There’s a cynical version of ADRs where they exist primarily as arse-covering - documentation created so that when something goes wrong, you can point to a name and say “they signed off on this.” If that’s the culture, ADRs will either become a box-ticking exercise or people will avoid making decisions at all. The Deciders field exists so you know who to ask questions, not who to blame. A decision that was reasonable given the information available at the time doesn’t become wrong because circumstances changed. If your organisation treats ADRs as ammunition for post-mortems, you’ll get defensive documentation rather than honest reasoning - and that defeats the entire purpose.
An example
Here’s a real example (with company-specific details redacted) of what this looks like in practice:
ADR-011: Database Sync Technology
Field Details Status Accepted Date August 2025 Deciders Sarah Chen Consulted/Informed Marcus Webb, James Liu Context
We need to migrate approximately 141 Azure SQL databases (47 databases across 3 regions) from existing dev/test/prod environments to new subscriptions within our secure Azure Landing Zone architecture. This migration is part of a broader platform modernisation initiative where we’re duplicating current infrastructure to enable a controlled cutover with minimal business disruption.
Key constraints:
- Database sizes: 5-15GB typical, with one 115GB outlier
- Downtime tolerance: 1-4 hours maximum per database
- CDC preservation: Critical for data pipelines - must preserve Change Data Capture configurations
- Rollback capability: Must support rapid fallback if issues arise
Decision
Implement Active Geo-Replication as the primary database migration strategy.
Migration approach:
- Enable geo-replication from source to target subscription days before cutover
- Allow initial seeding and synchronisation to complete
- Validate secondary database functionality and CDC preservation
- Perform planned failover during maintenance window
- Remove replication link to make secondary independent
- Reset identity columns (known issue with identity seed jumping)
- Test application functionality
Reasoning
CDC preservation: Active Geo-Replication is the only migration method that automatically preserves CDC schema and system objects. Manual reconfiguration across 141 databases would be error-prone and time-consuming.
Minimal downtime: Unlike BACPAC or Database Copy methods, geo-replication provides continuous synchronisation, reducing cutover downtime to minutes rather than hours.
Cross-subscription support: While Azure Portal doesn’t support cross-subscription replication, PowerShell commands work seamlessly across subscriptions within the same tenant.
Rollback safety: If issues arise post-cutover, we can re-establish replication in reverse or redirect applications back to source databases.
Consequences
Positive:
- No manual CDC reconfiguration required
- Cutover measured in minutes, not hours
- Can migrate databases individually or in groups
- Approximately 33% of manual migration effort costs
Negative:
- Additional eDTU costs for secondary databases during migration period
- Identity columns may jump by 1000 after replication removal (documented behaviour requiring mitigation script)
- Must monitor replication lag and health across all databases
Alternatives
Azure Database Migration Service - Rejected: Not designed for Azure SQL to Azure SQL migrations; fails to preserve CDC; limits to 4 databases per activity.
BACPAC Export/Import - Rejected: Requires databases offline during export; doesn’t preserve CDC; 4-6 hour window for 115GB database exceeds downtime tolerance.
Database Copy - Rejected: No ongoing synchronisation; explicitly excludes CDC artifacts; requires complete re-copy for any updates.
Failover Groups - Rejected: Doesn’t support database renaming; requires matching elastic pool names; over-engineered for one-time migration.
Notice what makes this useful: the Context explains why this decision was needed, the Reasoning connects the choice to specific constraints (CDC preservation, downtime tolerance), and the Alternatives show that other options were genuinely evaluated with concrete reasons for rejection. Six months later, anyone can understand not just what was decided, but why the rejected options wouldn’t have worked.
Making ADRs part of the workflow
The biggest failure mode for ADRs is writing them after the fact. If you’re documenting a decision that was made three months ago, you’re doing archaeology, not record-keeping. You’ll forget the alternatives you considered, the constraints that seemed important, the conversation that led to the conclusion.
Write the ADR during the decision. Better yet, write a draft before the decision and use it to structure the discussion. “Here are three options, here are the trade-offs, let’s pick one” is a more productive meeting than “so, what should we do about the gateway thing?”
A few other habits that help:
Give ADRs numbers and a lifecycle. ADR-001, ADR-002, etc. Status moves from Proposed → Accepted → Implemented. If a decision is later reversed, the ADR becomes “Superseded by ADR-042” rather than deleted. The history matters.
Store them somewhere discoverable. In the repo alongside the code is ideal. A wiki works if it’s actually maintained. A shared drive folder that requires three clicks and a search to find does not work.
Reference them in pull requests. “Implements ADR-015” in a PR description creates a paper trail and reminds reviewers that the approach was already agreed.
When not to write an ADR
Not every decision needs an ADR. Choosing between two npm packages for date formatting is probably not worth documenting. Choosing your primary database engine definitely is.
The heuristic I use: Would I regret not having this written down in six months? If the decision is:
- Difficult or expensive to reverse
- Likely to be questioned by someone who wasn’t in the room
- Part of a pattern that will be repeated across the codebase
- Relevant to compliance, security, or audit
…then write the ADR. If it’s easily reversible and low-stakes, probably don’t.
The point is context, not conclusions
The actual decision - “we chose Postgres” - is usually easy to reconstruct. You can look at the codebase and see what’s there. What’s not recoverable is the context: what constraints existed, what alternatives were considered, what trade-offs were accepted.
That context is what makes ADRs valuable. Not as a bureaucratic checkbox, but as institutional memory that survives staff turnover, fading recollections, and the inevitable “why on earth did we do it this way?” moments.
Conclusion
ADRs work when they’re lightweight enough to write during the decision, structured enough to answer questions six months later, and stored somewhere people actually look. Keep the template simple: Status, Date, Deciders, Consulted/Informed, Context, Decision, Reasoning, Consequences, and Alternatives. Use specific names so you know who to ask. Document the trade-offs honestly, including the downsides. Write it before or during the decision, not after. And remember that the goal is institutional memory, not arse-covering - a decision that was reasonable at the time doesn’t become wrong because circumstances changed.
The best ADRs are the ones you’re grateful to find. Aim for those.
Thanks for reading.
