Architecture Decision Record
A short structured document that captures a significant architectural decision, its context, and its consequences.
Architecture Decision Record
Section titled “Architecture Decision Record”An ADR is a lightweight record of a decision that was hard to make and will be hard to change. Its value is not in the decision itself but in the reasoning: future engineers who encounter the system and wonder “why is it built this way?” have an answer that does not depend on institutional memory. An ADR is a gift to your future self and to everyone who inherits the codebase.
The canonical ADR structure is three sections: Context (what forces were at play), Decision (what was chosen and why), and Consequences (what the decision costs and what it enables). Context is not history - it is the live forces at the time of the decision that made this the right call. Consequences are not just the good ones - a good ADR honestly names the tradeoffs.
Canonical template
Section titled “Canonical template”# [ADR-NNNN] [Decision Title]
## Status[Proposed | Accepted | Deprecated | Superseded by ADR-NNNN]
## Context[What forces were at play. The problem, the constraints, the alternatives considered.]
## Decision[What was decided. Be specific. Name the choice, not just the category.]
## Consequences### Positive- [benefit]### Negative- [tradeoff or cost]### Neutral- [consequence that is neither good nor bad]When to use
Section titled “When to use”Recording architectural decisions, capturing technology choices, documenting tradeoffs for future maintainers, team alignment on significant choices.
When not to use
Section titled “When not to use”Operational documentation, explaining how a system works, consumer-facing content.
Pairs well with
Section titled “Pairs well with”pragmatic-architect, operator, candid, matter-of-fact, problem-solution, comparison-contrast
Often confused with
Section titled “Often confused with”prd: A PRD defines what should be built and why. An ADR records a decision already made about how to build it.
Instruction
Section titled “Instruction”Write as an Architecture Decision Record (ADR). Use the canonical three-section structure:Context, Decision, Consequences. In Context: name the live forces at the time of decision - nothistory, but the constraints, options, and pressures that made this choice necessary. InDecision: name the specific choice, not just the category. In Consequences: be honest about thetradeoffs - name the negative consequences alongside the positive. The Consequences section iswhere ADRs earn their value. Do not omit the hard truths. Keep the document focused and short -an ADR that requires a 20-minute read is too long.Template
Section titled “Template”See the Architecture Decision Record template.
Related
Section titled “Related”Pairs well with
Section titled “Pairs well with”Pragmatic Architect, Operator, Candid, Matter of Fact, Problem-Solution, Comparison-Contrast
Avoid with
Section titled “Avoid with”Pastoral, Devotional Reflection, Reverent, Warm
Often confused with
Section titled “Often confused with”Examples
Section titled “Examples”ADR-0014: Adopt Async-First Standup Format
Section titled “ADR-0014: Adopt Async-First Standup Format”Status
Section titled “Status”Accepted
Context
Section titled “Context”The engineering team has grown from 6 to 11 engineers over 18 months. The team now spans four timezones: US Pacific (3 engineers), US Eastern (3 engineers), UK (2 engineers), India (3 engineers). The current synchronous standup is scheduled at 9am Pacific, which is 9:30pm India Standard Time.
Three forces pushed this decision:
Timezone asymmetry. The India-based engineers are disproportionately burdened by the meeting schedule. Attendance data from Q1 shows the three India engineers averaged 3.2 standup appearances per week out of 5, compared to 4.6 for US-based engineers. The shortfall is not disengagement - it is 9:30pm.
Information loss. Status shared verbally in the meeting does not persist. We have documented three incidents in the past quarter where an engineer spent more than an hour on a problem that had already been solved and discussed in a previous standup. There is no searchable record.
Meeting-to-value ratio. The standup averages 14 minutes. Analysis of the past month shows an average of 4.2 minutes of content that changed someone’s behavior - a blocker raised, a dependency flagged, a context shared. The remaining 10 minutes is status that required no response from anyone.
Alternatives considered: rotating the meeting time (solves equity but adds overhead and still does not create persistence), eliminating standup entirely (loses coordination value), and adopting an async tool like Geekbot (rejected on cost and added tooling complexity - Slack templates serve the same function).
Decision
Section titled “Decision”Replace the synchronous daily standup with an async standup update in #team-standup. Engineers post by 10am their local time using a pinned template:
- Shipped: what completed in the last 24 hours
- In progress: current focus
- Blocked / at risk: anything that needs attention, with @mention of the person who can resolve it
The on-call engineer reads the channel by 9am Pacific and responds to blocked items within 30 minutes during business hours. The synchronous standup slot is replaced with a 60-minute Thursday working session - not a status meeting, reserved for discussion requiring real-time exchange.
Consequences
Section titled “Consequences”Positive
Section titled “Positive”- All engineers participate on a schedule that fits their timezone
- Status information is persistent and searchable
- Blocked items route directly to the person who can resolve them via @mention
- Engineers recover 70 minutes per week previously spent in synchronous status reporting
Negative
Section titled “Negative”- Social cohesion that comes from shared daily presence is reduced; the Thursday session is a partial substitute but not equivalent
- The format depends on consistent participation - if engineers stop posting, the channel’s value drops for everyone
- Blockers that require nuance are harder to surface in a structured three-field template than in a live conversation
Neutral
Section titled “Neutral”- On-call rotation adds a daily channel-reading responsibility, but this replaces the meeting facilitation responsibility previously on the same rotation
- The Thursday working session is new overhead for some engineers who previously skipped standup
ADR-001: Adopt a Structured First Hour After Waking
Section titled “ADR-001: Adopt a Structured First Hour After Waking”- Date: 2026-05-14
- Status: Accepted
- Decider: Me
- Consulted: Spouse, accountability partner
1. Context
Section titled “1. Context”I currently wake at 6:30am and reach for my phone before my feet hit the floor. The first 45 minutes of the day are spent scrolling Slack, email, and news. By 7:30am, family obligations begin (breakfast, school dropoff, lunches), and by 9am the work day starts. The result: I begin every weekday already reactive, already drained, and already a step behind my own intentions.
I have tried “just stop using my phone in the morning” three times in the past year. Each attempt lasted four to six days. The failures share a pattern: I removed a behavior without replacing it. The vacuum collapsed back into the old habit.
A structured morning routine is well-trodden ground. The novelty here is not the content. It is committing to a specific design and documenting why, so that future-me cannot quietly renegotiate the terms.
2. Decision
Section titled “2. Decision”Between 6:30am and 7:30am on weekdays, I will execute a four-module morning routine in this order:
- Water (8oz, immediately on rising)
- Light (10 minutes outside or by the largest window available)
- Movement (15 minutes - walk, stretch, or bodyweight)
- Planning (10 minutes with a paper notebook, no screen)
The phone stays in the kitchen, plugged in, face down, until 7:30am.
3. Consequences
Section titled “3. Consequences”Positive
Section titled “Positive”- The first hour becomes proactive rather than reactive.
- The phone-in-kitchen rule removes the decision point; I do not have to resist scrolling because the device is not within reach.
- Paper-based planning forces me to think before I touch any work tool. By 9am I arrive at my desk with a written shortlist.
Negative
Section titled “Negative”- I will miss early Slack messages from West Coast colleagues. Risk accepted - urgent issues can reach me by phone call.
- The routine requires going to bed earlier. Current bedtime drift (11:30pm-ish) will need to compress to 10:30pm.
- Family mornings may need light renegotiation. My spouse’s coffee window currently runs 6:45-7:15am; I will defer conversation to 7:15am.
Neutral
Section titled “Neutral”- This is a one-month commitment, after which I will revisit. If module ordering proves wrong (for example, planning before movement), reorder rather than abandon.
4. Alternatives Considered
Section titled “4. Alternatives Considered”- Do nothing. Rejected. Current state is the problem.
- Wake earlier (5:30am). Rejected as premature optimization. Fix the existing hour before adding a new one.
- Use a habit-tracking app. Rejected. Adds a screen to a routine whose purpose is partly to escape screens.
5. Review
Section titled “5. Review”Revisit on 2026-06-14. If module completion rate is below 70 percent of weekdays, escalate to a session with the accountability partner before changing the design.
ADR-0023: Use Postgres for the Notification Service
Section titled “ADR-0023: Use Postgres for the Notification Service”Status
Section titled “Status”Accepted
Context
Section titled “Context”Lattice Notify is launching a real-time notification system that needs a new persistent data store. The system will handle 500K notification events per day at launch, with a 10x growth scenario in 12 months if the pending Slack-partnership deal closes. The decision sits between two candidates:
- Option A: Postgres. Extend the existing Postgres footprint with a new schema, add a job queue, and absorb the resulting scaling work. The team has operated Postgres at this scale before. Cross-database queries against the existing monolith data stay simple.
- Option B: DynamoDB. Adopt a new datastore that fits the notification access pattern (write-heavy, point-lookups by user) and scales without operator intervention. The team has no production DynamoDB experience. Ops surface area doubles. There is no rollback plan if it goes wrong.
Three forces pushed this decision:
Team operational capacity. We have 8 backend engineers and a 4-person on-call rotation. Adding a second database adds a second runbook, a second monitoring surface, a second backup story, and a second debugging skillset on every page. We have measured this cost before in a separate workstream and it is non-trivial.
Growth uncertainty. The 10x growth scenario depends on a deal that has not closed. Designing the system for the larger scenario, when the smaller one is the certain one, optimizes for the case that may not arrive.
Reversibility cost. If we choose Postgres and outgrow it, we incur 3-6 weeks of rework to migrate. If we choose DynamoDB and find we need cross-database joins for product features, we incur similar rework plus a team that has learned the wrong tool. The asymmetry is small; both choices are recoverable.
Marcus made a strong case for DynamoDB’s access-pattern fit. Ana raised the operational capacity concern. The architecture meeting on Wednesday confirmed that the operational concern is the load-bearing one.
Decision
Section titled “Decision”Build the notification service on Postgres, using a new schema (notifications) in the existing primary cluster and a job queue backed by pg_notify plus a notification_jobs table. Provision read replicas to absorb fanout reads. Add a documented threshold (5M events/day sustained) at which we revisit DynamoDB before scaling the Postgres path further.
Priya has the decision recorded for the Friday sprint planning.
Consequences
Section titled “Consequences”Positive
Section titled “Positive”- Single operational surface for the 4-person on-call rotation. No new runbooks, no new monitoring, no new debugging skillset on call.
- Cross-database queries (joining notifications to users, accounts, workspaces) remain simple SQL.
- The team ships the launch scope on familiar ground. Estimated 3 weeks faster to first production traffic than the DynamoDB path.
- The decision is reversible: if we cross the 5M events/day threshold, we have the data and the operational margin to plan a migration.
Negative
Section titled “Negative”- We will likely need to do non-trivial Postgres tuning at the 10x growth point: partitioning the notifications table, tuning the job queue, possibly sharding. This work is real and is on the roadmap, not avoided.
- Marcus’s argument about access-pattern fit is correct in isolation; we are accepting a worse fit for the access pattern in exchange for a better fit for the team’s operational reality.
- If the Slack deal closes and growth arrives faster than 12 months, we hit the rework window earlier than planned.
Neutral
Section titled “Neutral”- The
notification_jobstable becomes a new operational concern: queue depth, dead-letter handling, retry policy. These are familiar problems on a familiar platform. - The 5M events/day revisit threshold becomes a tracked metric. The on-call rotation owns the dashboard.
Appears in diff-pairs
Section titled “Appears in diff-pairs”- adr vs whitepaper (varies format)