It’s 6 months into the project. A new developer joins the team and asks a reasonable question:
“Why are we using Postgres instead of MongoDB?”
You pause. You remember there was a discussion. Someone had strong opinions. There were tradeoffs. But the details? Gone. Lost in a Slack thread from March that you’d have to scroll through 1000 messages to find.
So you give the worst possible answer: “I think it was because… something about transactions? Maybe ask Sarah—wait, Sarah left last month.”
Now the new developer is confused. They start questioning the choice. Pretty soon, someone suggests “Maybe we should switch to MongoDB.” And you’re back in the same debate you already had, burning time re-evaluating a decision you made six months ago.
This is why we document decisions.
Not to create bureaucracy. Not to satisfy some compliance checklist. But to preserve the why behind technical choices so teams don’t waste time re-debating what they already decided.
Enter: Architecture Decision Records (ADRs).
What Is an ADR?
An Architecture Decision Record is a short document that captures:
- What decision was made (e.g., “Use Postgres for primary data storage”)
- Why it was made (e.g., “Need ACID transactions, existing team expertise”)
- What alternatives were considered (e.g., MongoDB, DynamoDB)
- What consequences result from this choice (e.g., “Pro: Strong consistency. Con: Harder to scale horizontally”)
That’s it. No diagrams. No UML. No 10-page technical specs. Just:
- Context: Why are we making this decision?
- Decision: What did we choose?
- Alternatives: What else did we consider?
- Consequences: What are the tradeoffs?
ADRs live in your repo, usually in .assistant/adr/ or docs/adr/, and they’re numbered sequentially: ADR-001, ADR-002, etc.
Why ADRs Matter
1. Prevent Re-Debates
Without ADRs, teams re-debate decisions every time:
- A new person joins
- Someone forgets why a choice was made
- A similar problem comes up and people want to “revisit the approach”
With ADRs, you respond: “We chose Postgres in ADR-003. Here’s why. If conditions have changed, let’s write ADR-015 to revisit it.”
Now you’re building on past decisions instead of relitigating them.
2. Preserve Context
Six months from now, you won’t remember why you chose JWT over sessions. But ADR-007 will. It captures the context (stateless APIs), the tradeoffs (no server-side session store, but tokens can’t be revoked easily), and the rationale.
Future you is grateful.
3. Onboard New Team Members
New developers read the ADRs and understand the architecture’s history in an hour instead of piecing it together over three weeks by reading code and asking questions.
They learn:
- Why the database is Postgres (ADR-003)
- Why auth uses JWT (ADR-007)
- Why we deploy to AWS instead of GCP (ADR-011)
- Why we picked REST over GraphQL (ADR-005)
They understand not just what the system is, but why it was designed that way.
4. Enable Better Decisions
When you document decisions, you force yourself to articulate the tradeoffs. This surfaces assumptions and catches bad reasoning before it becomes code.
Writing “We chose MongoDB because it’s webscale” forces you to realize that’s not a real reason. Writing “We chose MongoDB because we need flexible schema evolution and don’t require transactions” is a real reason you can evaluate.
5. Make “Revisiting” Honest
Sometimes you need to change a decision. Maybe requirements changed. Maybe you learned something new. Maybe the original choice was wrong.
ADRs make this legitimate. You write ADR-015: “Supersede ADR-003 (Postgres) — Migrate to MongoDB for flexible schema needs.”
Now it’s clear:
- We made a choice (ADR-003)
- Conditions changed (documented in ADR-015)
- We’re consciously reversing it (not flip-flopping)
This prevents decision thrashing where teams bounce between choices without learning.
The ADR Template
Here’s the minimal ADR structure:
# ADR-XXX — [Short Title of Decision]
**Date:** YYYY-MM-DD
**Status:** Proposed | Accepted | Deprecated | Superseded by ADR-YYY
## Context
What's the situation? What problem are we solving? What constraints exist?
## Decision
What did we decide? Be specific. Name technologies, patterns, approaches.
## Alternatives Considered
What else did we look at? Why didn't we choose them?
## Consequences
### Pros
- What benefits come from this decision?
### Cons
- What tradeoffs or risks are we accepting?
### Neutral
- What changes but isn't strictly good or bad?
That’s 5 sections. Total writing time: 10-15 minutes. Total value: months of saved time.
Real Example: Database Choice
Here’s an ADR for a real technical decision:
# ADR-003 — Use Postgres for Primary Data Storage
**Date:** 2026-02-15
**Status:** Accepted
## Context
We need a database for user accounts, authentication state, and application data. Requirements:
- Must support ACID transactions (payment processing requires consistency)
- Must handle structured relational data (users → roles → permissions)
- Must scale to 10k concurrent users initially
- Team has Postgres experience but limited NoSQL experience
- Budget: $50-200/month for managed database
## Decision
Use **PostgreSQL 16** (managed via AWS RDS) as the primary data store.
## Alternatives Considered
### MongoDB
- **Pro:** Flexible schema, horizontally scalable, good for rapid iteration
- **Con:** No multi-document transactions (added in 4.0 but less mature than Postgres), team has no production experience, harder to query relational data
- **Verdict:** Doesn't meet ACID requirements for payments
### DynamoDB
- **Pro:** Fully managed, scales effortlessly, pay-per-request pricing
- **Con:** No joins, no complex queries, expensive at scale, steep learning curve, poor fit for relational data model
- **Verdict:** Wrong tool for relational use case
### MySQL
- **Pro:** Mature, widely supported, similar to Postgres
- **Con:** Less advanced features (JSONB, full-text search, array types), licensing concerns (Oracle ownership)
- **Verdict:** Postgres offers better feature set for our needs
## Consequences
### Pros
- Strong ACID guarantees for payment transactions
- Mature relational model fits our data structure (users, roles, sessions)
- Team already knows Postgres (faster development, fewer mistakes)
- JSONB support allows flexible schema where needed
- Rich ecosystem (pgBouncer for connection pooling, PostGIS if we add location features)
### Cons
- Vertical scaling limits (eventually need read replicas if traffic exceeds single-instance capacity)
- Slightly slower write performance than NoSQL for unstructured data
- AWS RDS adds ~$50/month cost (vs free-tier MongoDB Atlas)
### Neutral
- Migration to another database would require significant refactoring (not a short-term concern)
- Requires connection pooling strategy for high concurrency (planned: pgBouncer)
When to Write an ADR
Write an ADR whenever you make a decision that:
1. Affects System Architecture
- Database choice
- Authentication strategy
- API design (REST vs GraphQL vs gRPC)
- Hosting platform (AWS vs GCP vs self-hosted)
- Framework choice (React vs Vue, Express vs Fastify)
2. Has Long-Term Consequences
- Licensing decisions (open source vs proprietary)
- Data retention policies
- Infrastructure patterns (microservices vs monolith)
- CI/CD pipeline design
3. Involves Significant Tradeoffs
- Performance vs developer experience
- Security vs convenience
- Cost vs scalability
- Flexibility vs simplicity
4. Requires Team Consensus
If you need to discuss it in a meeting, you need an ADR. Write the decision down afterward.
Don’t Write ADRs For…
Implementation Details: Don’t document “We used a for-loop instead of .map()” — that’s code, not architecture.
Obvious Choices: Don’t write “Use Git for version control” unless there’s a real alternative you considered.
Temporary Workarounds: Don’t document “We added a hack to fix the bug” — that’s technical debt, not a decision you’re defending.
Personal Preferences: Don’t write “We use tabs instead of spaces” — that’s a style guide, not architecture.
How to Write ADRs Without Slowing Down
The #1 complaint about ADRs: “We don’t have time to write documentation.”
Here’s how to keep ADRs lightweight:
1. Write Them Immediately After Deciding (5 minutes)
Don’t wait until the end of the sprint. Write the ADR right after the decision, while the context is fresh. It takes 5 minutes now or 30 minutes later when you’ve forgotten the details.
2. Use a Template (Pre-Fill Sections)
Copy your template, fill in the blanks. Don’t overthink it.
cp .assistant/adr/ADR-TEMPLATE.md .assistant/adr/ADR-012.md
3. Be Concise (1 Page Maximum)
If your ADR is over 1 page, you’re writing a spec, not a decision record. Compress.
4. Link, Don’t Duplicate (Reference External Docs)
Don’t paste code samples or detailed implementation notes. Link to them.
See [JWT implementation guide](https://auth-docs.example.com/jwt) for details.
5. Draft in Meetings (Capture Decisions in Real-Time)
During architecture discussions, have someone draft the ADR in a shared doc. By the end of the meeting, it’s 80% done. Polish it later.
Maintaining ADRs Over Time
ADRs aren’t set in stone. They evolve.
Statuses
- Proposed: Under discussion, not yet decided
- Accepted: Decided and implemented
- Deprecated: No longer relevant (e.g., “use MySQL” → we’re now on Postgres)
- Superseded by ADR-XXX: Replaced by a newer decision
Updating vs Creating New ADRs
Don’t edit old ADRs (destroys history). Instead:
- Mark old ADR as “Superseded by ADR-XXX”
- Write new ADR explaining the change and why
- Link them together
Example:
# ADR-003 — Use Postgres for Primary Data Storage
**Status:** Superseded by ADR-018 (Migrated to Aurora Serverless)
Now the history is clear: we chose Postgres (ADR-003), conditions changed (high traffic + cost), we switched to Aurora (ADR-018).
Real ADRs from the Wild
Let’s look at three more realistic examples:
ADR-007: JWT vs Session-Based Auth
# ADR-007 — Use JWT Tokens for Authentication
**Date:** 2026-02-20
**Status:** Accepted
## Context
Need stateless authentication for API that serves web + mobile clients. Must scale horizontally without shared session store.
## Decision
Use **JWT tokens** (RS256 signing) with 24-hour expiry + 30-day refresh tokens.
## Alternatives
**Session-based auth (cookie + Redis):**
- Pro: Tokens revocable immediately
- Con: Requires shared Redis, stateful, harder to scale
**OAuth only (delegate to Auth0):**
- Pro: Outsource complexity
- Con: Vendor lock-in, $23/mo minimum, users can't own their data
## Consequences
**Pros:**
- Stateless (any server can validate token)
- Works for web + mobile
- No shared session store
**Cons:**
- Can't revoke tokens before expiry (mitigation: keep expiry short)
- Slightly larger payload than session IDs
ADR-011: Deploy to AWS vs GCP
# ADR-011 — Deploy Infrastructure to AWS
**Date:** 2026-03-01
**Status:** Accepted
## Context
Need cloud hosting for production app. Must support: container orchestration, managed DB, CDN, monitoring.
## Decision
Use **AWS** (ECS Fargate + RDS + CloudFront).
## Alternatives
**Google Cloud Platform:**
- Pro: Better Kubernetes (GKE), cheaper egress
- Con: Team has no GCP experience (training cost)
**Self-hosted (DigitalOcean):**
- Pro: Cheaper ($20/mo vs $200/mo)
- Con: No team to manage infra, single point of failure
## Consequences
**Pros:**
- Team knows AWS (faster setup, fewer mistakes)
- Mature ecosystem (Fargate = no servers to manage)
- CloudFront CDN built-in
**Cons:**
- Higher cost than GCP/DO (~$200/mo)
- Vendor lock-in (would take weeks to migrate)
ADR-015: Monorepo vs Multi-Repo
# ADR-015 — Use Monorepo for Frontend + Backend
**Date:** 2026-03-10
**Status:** Accepted
## Context
We have a React frontend and Node.js backend. They share TypeScript types. Need versioning strategy.
## Decision
Use **monorepo** (pnpm workspaces) with shared packages.
## Alternatives
**Multi-repo (separate repos for FE/BE):**
- Pro: Independent versioning, clear boundaries
- Con: Type sync pain, duplicate tooling config, harder to coordinate changes
**Separate repos + published types package:**
- Pro: Types stay in sync via npm
- Con: Extra publish step, versioning complexity
## Consequences
**Pros:**
- Shared types directly imported (no publish step)
- Single CI/CD pipeline
- Atomic commits across FE/BE
**Cons:**
- Larger repo clone size
- Requires workspace-aware tooling (pnpm/nx)
Try It Yourself
Think of the last major technical decision you made. Write an ADR:
- Context: What problem were you solving?
- Decision: What did you choose?
- Alternatives: What else did you consider?
- Consequences: What are the pros, cons?
Set a timer for 10 minutes. Write it. You now have a decision preserved for future you (and your team).
Next time someone asks “Why did we choose X?”, you respond: “See ADR-XXX.”
No more lost context. No more re-debating. No more “I think Sarah mentioned something about…?”
Just clear, documented decisions that save time and prevent amnesia.
Coming in Post 6: Copy This Template and Ship Faster — Get started in 5 steps: copy the template, generate a TRD, fill the canvas, create your plan, and start your first session. Plus: command reference, common setup mistakes, and FAQs.
Keywords: architecture decision records, ADR, technical documentation, decision documentation, software architecture, team knowledge management