Architecture Decision Records: Why and How

A practical guide to documenting architectural decisions using ADRs, with templates and real-world examples.

Get Started
 

Architecture Decision Records

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:

  1. Team expertise (2/5 engineers know PostgreSQL)
  2. ACID requirements for financial accuracy
  3. Complex query needs for reporting
  4. Budget constraints (open-source)
  5. 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:


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:

  1. Pick an architecturally significant decision you’re facing now
  2. Draft an ADR using the template above
  3. Share it with your team for feedback
  4. Make the decision and accept the ADR
  5. 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

Ready to discuss?

If this blog post has sparked your interest, let's talk about how Tek42 can help your organisation.

Contact Us

Ready to Get Started?

Let's discuss how Tek42 can help with your architecture decision records: why and how.

Contact Us View All Services