
Six months after a major architectural decision, someone inevitably asks: “Why did we do it this way?” The original context has faded. Key people have moved to other teams. The discussion happened in a meeting room or Slack thread that’s long gone.
The result: teams second-guess past decisions, repeat old debates, or worse, make changes that reintroduce problems the original decision solved.
Architecture Decision Records (ADRs) solve this problem by capturing the “why” behind architectural choices in lightweight, version-controlled documents.
What Are Architecture Decision Records?
An ADR is a short document that captures a single architectural decision, including:
- The context and problem being addressed
- The decision made and why
- The consequences (trade-offs, risks, benefits)
- Alternative options considered
- Current status (proposed, accepted, deprecated, superseded)
ADRs live in your codebase (usually docs/adr/ or similar), are numbered sequentially, and stay immutable once accepted, creating a historical record of architectural evolution.
Why ADRs Matter
For Current Teams
Clarity on Trade-offs Every architectural decision involves trade-offs. ADRs make these explicit, preventing endless debates about “why didn’t we choose X instead?”
Shared Understanding When teams understand why decisions were made, they work with the architecture instead of against it.
Decision Velocity Stop relitigating old decisions. “We already decided this, see ADR-023” ends debates quickly.
For Future Teams
Onboarding New Members New team members can read through ADRs to understand the architectural journey and current state.
Understanding Legacy Code That weird pattern in the codebase? ADR-015 explains it was a deliberate trade-off for performance.
Knowing When to Change When contexts change, ADRs help evaluate whether the original decision still makes sense.
For Organisations
Knowledge Retention Architectural knowledge doesn’t leave with key engineers. It’s captured in version control.
Accountability & Transparency Decisions are documented with rationale, making it clear who decided what and why.
Pattern Recognition Over time, ADR collections reveal patterns in decision-making and help teams learn from past choices.
When to Write an ADR
Not every decision needs an ADR. Use them for architecturally significant decisions, choices that affect:
System Structure
- Microservices vs. monolith
- Service boundaries and communication patterns
- Database per service vs. shared database
- Event-driven vs. request-response
Technology Selection
- Programming languages and frameworks
- Databases and storage systems
- Cloud providers and services
- Infrastructure as code tools
Cross-Cutting Concerns
- Authentication and authorization approach
- Logging, monitoring, and observability strategy
- Error handling patterns
- API design conventions
Quality Attributes
- Performance optimisation approaches
- Security architecture decisions
- Scalability strategies
- Reliability and resilience patterns
Rules of Thumb
Write an ADR if:
- The decision affects multiple teams or services
- Reversing the decision would be costly (weeks/months of work)
- The decision involves significant trade-offs
- People might reasonably ask “why did we do it this way?” later
Don’t write an ADR for:
- Routine implementation choices (which library for date formatting)
- Decisions easily changed with low cost
- Purely local decisions affecting single module
- Obvious choices with no real alternatives
ADR Template
Here’s a proven template (adapted from Michael Nygard’s original format):
# ADR-NNN: [Short Title]
## Status
[Proposed | Accepted | Deprecated | Superseded]
## Context
What is the issue that we're seeing that is motivating this decision or change?
## Decision
What is the change that we're proposing and/or doing?
## Consequences
What becomes easier or more difficult to do because of this change?
## Alternatives Considered
What other options did we evaluate? Why did we reject them?
## Date
When was this decision made?
## Participants
Who was involved in making this decision?
Section-by-Section Guide
Title: Short, descriptive, action-oriented
- Good: “Use PostgreSQL for primary database”
- Good: “Adopt microservices for order management”
- Bad: “Database decision”
- Bad: “Thoughts on architecture”
Status: Lifecycle tracking
- Proposed: Under discussion, not yet decided
- Accepted: Decision made and being implemented
- Deprecated: Still in effect but don’t use for new work
- Superseded: Replaced by a newer ADR (reference the new one)
Context: The “why now?”
- What problem are we solving?
- What constraints exist (technical, business, team)?
- What are the forces at play (performance, cost, time, skills)?
- What assumptions are we making?
Keep it focused: 3-5 paragraphs maximum. Future readers need enough context to understand the situation without rehashing the entire project.
Decision: The “what”
- State the decision clearly in 1-2 sentences
- Use active voice: “We will use…” not “It was decided…”
- Be specific: “PostgreSQL 14 with TimescaleDB extension” not “a database”
Consequences: The “so what?”
- What becomes easier because of this decision?
- What becomes harder?
- What risks do we accept?
- What new capabilities do we gain?
- What constraints do we impose?
Be honest about trade-offs. Every decision has downsides. Documenting them prevents future surprises.
Alternatives Considered: The “why not X?”
- What other options did we evaluate?
- Why did we reject each alternative?
- What would have to change for an alternative to be better?
This section is gold for future teams. When contexts change, they can revisit alternatives with new information.
Date: When was this decided? Format: YYYY-MM-DD for sortability
Participants: Who was involved? Useful for future questions and accountability
Real-World Example
Let’s walk through a concrete example:
ADR-007: Use PostgreSQL for Primary Database
Status: Accepted
Context
We’re building a SaaS application for project management with the following requirements:
- Multi-tenant architecture with data isolation
- Support for complex queries (reporting, analytics)
- ACID transactions for consistency
- Expected to scale to 10,000 customers within 2 years
- Team has limited database expertise (2 engineers with PostgreSQL experience, 0 with alternatives)
- Budget constraints favour open-source solutions
- Need strong community support and ecosystem
Our current MVP uses SQLite, which won’t scale to production needs. We must choose a primary database for production launch in 8 weeks.
Decision
We will use PostgreSQL 15 as our primary database for all application data.
Specifically:
- PostgreSQL 15 on AWS RDS for managed infrastructure
- One database per tenant for data isolation
- Use Prisma ORM for schema management and migrations
- Enable pgvector extension for future ML/semantic search features
Consequences
What becomes easier:
- Complex queries: PostgreSQL’s query planner handles joins and aggregations well
- ACID transactions: Strong consistency guarantees for financial data
- JSON support: Can store flexible schema data where needed (user preferences, custom fields)
- Full-text search: Built-in FTS capabilities (we don’t need Elasticsearch initially)
- Team expertise: 2 engineers already know PostgreSQL well
- Rich ecosystem: Massive community, mature tools, extensive documentation
- Cost-effective: Open-source, no licensing fees
What becomes harder:
- Horizontal scaling: More complex than NoSQL options (though vertical scaling sufficient for 2-3 years)
- Schema changes: Migrations require downtime (milliseconds typically, but planned)
- NoSQL-style flexibility: Rigid schema compared to MongoDB (trade-off we accept for consistency)
Risks we accept:
- Vendor-specific features: Some PostgreSQL-specific SQL might make future migration harder
- Single point of failure: RDS mitigates this with Multi-AZ, but PostgreSQL itself is SPOF in our architecture
New capabilities:
- Can build complex reporting without external data warehouse initially
- JSONB columns allow flexibility for tenant-specific customization
- PostGIS extension available if we add location features
- pgvector positions us for future AI/ML features
Alternatives Considered
MongoDB
- Pros: Flexible schema, horizontal scaling, familiar to some team members
- Cons: Weaker transaction guarantees, complex to maintain consistency across documents, team less experienced
- Why rejected: ACID transactions are critical for financial data; flexibility not needed; consistency > scalability at our scale
MySQL
- Pros: Similar to PostgreSQL, widely used, good tooling
- Cons: JSON support weaker, less powerful query planner, licensing concerns (Oracle ownership)
- Why rejected: PostgreSQL’s JSON, array, and advanced features tilt decision; no compelling reason to choose MySQL
Amazon Aurora PostgreSQL
- Pros: Better read scaling, automatic storage scaling, faster failover
- Cons: 20% more expensive, proprietary extensions, vendor lock-in
- Why rejected: Standard RDS PostgreSQL sufficient for our scale; can migrate to Aurora later if needed without code changes
Decision Drivers:
- Team expertise (2/5 engineers know PostgreSQL)
- ACID requirements for financial accuracy
- Complex query needs for reporting
- Budget constraints (open-source)
- Time to production (8 weeks, no time to learn new database)
What would have to change:
- If we needed to scale reads to 100M+ queries/day → Consider Aurora or read replicas
- If data became primarily document-oriented → Reconsider MongoDB
- If we built real-time collaborative features → Consider adding Redis or WebSocket-specific datastore
Date: 2026-01-07
Participants:
- Jane Doe (CTO) - Decision maker
- John Smith (Lead Backend Engineer) - Technical evaluation
- Sarah Johnson (Product Manager) - Requirements input
- Mike Chen (DevOps Engineer) - Operations input
References:
- PostgreSQL vs. MongoDB comparison research
- AWS RDS vs. Aurora cost analysis
- Schema design discussion in Slack
ADR Workflow
1. Recognize a Decision Point
Someone (engineer, architect, product manager) identifies an architecturally significant decision needed.
2. Draft the ADR
Create a new file: docs/adr/007-use-postgresql-for-primary-database.md
Status: Proposed
Fill in Context, alternatives, and draft the Decision. Don’t worry about perfection. This is a starting point for discussion.
3. Discuss & Refine
Share the ADR draft with stakeholders:
- Post in Slack/Teams for async feedback
- Schedule decision meeting if needed
- Update ADR with new information and perspectives
- Iterate until key stakeholders align
Duration: typically 1-7 days depending on decision significance
4. Decide & Accept
Once the decision is made:
- Update Status to Accepted
- Add Date and Participants
- Commit to version control
- Announce decision to team with link to ADR
5. Implement & Learn
As you implement the decision:
- Reference the ADR in relevant code comments
- Update the ADR if you discover new consequences
- If the decision was wrong, write a new ADR superseding this one (don’t delete the original; history matters)
6. Review & Deprecate
Periodically review ADRs:
- Are they still relevant?
- Have contexts changed?
- Should any be deprecated or superseded?
Common Mistakes
Mistake 1: Writing ADRs After the Fact
Problem: “Let me document that decision we made 6 months ago…”
Why it fails: You’ve forgotten the context, alternatives, and trade-offs. The ADR becomes a justification instead of documentation.
Fix: Write ADRs during decision-making, not after. They’re most valuable as thinking tools.
Mistake 2: Too Much Detail
Problem: 10-page ADR with implementation details, code snippets, and exhaustive research.
Why it fails: Nobody reads it. The signal gets lost in noise.
Fix: Keep ADRs concise (1-2 pages). Link to detailed research elsewhere. Focus on decision and rationale, not implementation.
Mistake 3: Treating ADRs as Immutable Law
Problem: “We can’t do X because ADR-015 says so.”
Why it fails: Contexts change. Good decisions become bad decisions over time.
Fix: ADRs are records, not rules. When contexts change, write a new ADR superseding the old one. Document what changed and why.
Mistake 4: Analysis Paralysis
Problem: Spending weeks perfecting an ADR before deciding.
Why it fails: Decision-making stalls. Analysis paralysis sets in.
Fix: Timebox ADR discussion (3-7 days typical). Perfect is the enemy of done. Decide, document, move forward.
Mistake 5: Not Documenting Alternatives
Problem: ADR only documents what you chose, not what you didn’t.
Why it fails: Future teams don’t understand why obvious alternatives weren’t chosen. Old debates repeat.
Fix: Always document alternatives considered and why you rejected them. This section is often the most valuable.
ADR Tools & Practices
Where to Store ADRs
Option 1: In the codebase (docs/adr/)
- Pros: Version-controlled with code, developers see them
- Cons: Not visible to non-engineering stakeholders
Option 2: In a docs repo (separate from code)
- Pros: Cross-project ADRs, broader visibility
- Cons: Can drift from code, harder to enforce
Option 3: In documentation tools (Confluence, Notion)
- Pros: Easy to browse, familiar to non-engineers
- Cons: Not version-controlled, can become stale
Recommendation: Start in codebase (docs/adr/). Move to docs repo if you need cross-project ADRs.
Naming Convention
docs/adr/
001-use-markdown-for-adrs.md
002-adopt-microservices-for-order-management.md
003-choose-react-for-frontend.md
...
- Sequential numbering (pad with zeros:
001,002, …) - Lowercase with hyphens
- Start with verb (use, adopt, choose, implement)
- Keep titles short (< 60 characters)
Tools
adr-tools (https://github.com/npryce/adr-tools)
- Command-line tool for creating and managing ADRs
adr new "Use PostgreSQL for primary database"- Automatically numbers and scaffolds ADR template
Backstage (Spotify’s developer portal)
- Can display ADRs alongside service documentation
- Provides discoverability and searchability
Custom Scripts
- Generate ADR list/index automatically
- Validate ADR format in CI/CD
- Link ADRs to related code in comments
Conclusion
Architecture Decision Records are lightweight, high-leverage documentation. They:
- Capture the “why” behind architectural choices
- Prevent debates from repeating endlessly
- Help new team members understand the system
- Enable informed future changes
Start small:
- Pick an architecturally significant decision you’re facing now
- Draft an ADR using the template above
- Share it with your team for feedback
- Make the decision and accept the ADR
- Reference it when questions come up later
Over time, you’ll build a valuable historical record that makes your architecture understandable and evolvable.
The best time to start using ADRs was on your last architectural decision. The second-best time is right now.
Need help establishing ADR practices or facilitating architectural decisions? Contact Tek42 to discuss how our Strategic Architecture Workshops can help.
Related Services: Strategic Architecture Workshops | Fractional CTO Services