An Introduction to ADRs (Architecture Decision Records) — The Minimal Way to Record 'Why We Designed It This Way' on a Small Team
· Go Komura · Design, Design Review, Documentation, ADR, Technical Consulting, Maintenance, Contract Development, Windows Development
“Why is this using a file handoff? Wouldn’t it be simpler to just query the database?” — a developer who opens up the code of a system they’ve inherited runs into a question like this almost without fail. And more often than not, whoever knew the answer has already left the project.
There was surely a reason. Maybe permission to connect directly to the other system’s database was never granted, or maybe that was the only method safe enough to hit the deadline at the time. But if that reasoning isn’t preserved, the successor either freezes in front of code they don’t know if it’s safe to touch, or barrels ahead and breaks the very thing the reasoning was protecting.
On this blog, we’ve covered how to run a contract-development engagement in What to Sort Out Before Outsourcing Windows App Development, and the contract framework in Choosing Between a Quasi-Mandate and a Contract for Work — Lessons From IPA’s “Model Transaction and Contract”. This article picks up from there, covering what it takes to keep a system running for years after it’s built. We explain ADRs (Architecture Decision Records) — a mechanism for preserving the reasoning behind a design decision with minimal effort — assuming a small contract-development or in-house development setting.
1. The Bottom Line First
- Before an exhaustive design document, you should be preserving a record of decisions. What really causes trouble during maintenance isn’t not knowing what the code does — it’s not knowing why it was done that way.
- An ADR is a lightweight format that writes up a single decision in one file, using the fixed shape title / status / context / decision / consequences. Michael Nygard proposed it in 2011, and the rule of thumb is one to two pages per decision, at most.1
- It lives in the same repository as the code (e.g.,
docs/adr/0001-title.md) — under version control alongside the code, reviewed together with the code review, rather than in a wiki or a shared folder.12 - A decision is never overwritten. When you change direction, add a new ADR and set the old ADR’s status to Superseded, with a cross-reference between the two. An ADR log is append-only.2
- Rather than writing up everything, write up only decisions that are hard to change later, had several equally reasonable alternatives, or were decided by a constraint. Naming rules and formatter settings are out of scope.2
- In my own experience, keeping each one to 15-30 minutes of writing is what makes the habit stick. A heavyweight template dies out after the first three entries.
- In contract development, an ADR becomes a deliverable you can share with the client. It works as-is as an explanatory document at acceptance time, and as a handover document when staff or vendors change.
2. The “Why Is It Like This?” Problem
2.1 Code Tells You What, Never Why
Read the code and, given enough time, you can figure out what it does. What you can’t figure out is the why behind things like these.
- Why is the database SQLite instead of SQL Server?
- Why does integration with the other system pass CSV files around instead of using a web API?
- Why does only this one report launch Excel to print?
- Why is it still on .NET Framework instead of upgraded to current .NET?
Behind decisions like these there is always a reason that lives outside the code itself — the budget and deadline at the time, constraints on the customer’s side, the trade-offs against existing assets. It’s too big to fit in a comment, and “the history of how we got to this decision” doesn’t fit comfortably in a design document either. The end result is that the reason survives nowhere at all.
2.2 Every Place We Usually Keep a Decision Disappears Within a Few Years
So where does the reasoning behind a design decision actually live today? Let’s compare the usual places.
| Where it’s kept | Still there years later? | Distance from the code | Can a successor find it? |
|---|---|---|---|
| A verbal agreement in a meeting | Doesn’t survive | – | Impossible |
| Chat (Teams/Slack) | Scrolls away, effectively gone | Far | Nearly impossible |
| Buried in someone’s personal inbox | Far | Gone once they leave | |
| Meeting minutes (a shared folder) | Survives, but a mixed bag | Far | Don’t know which meeting’s minutes to look in |
| Wiki / design document | Updates stop, drifts out of sync | Far | Findable, but not trustworthy |
| ADR (in the repository) | Survives right alongside the code | Same repository | Just open docs/adr/ |
Microsoft’s architecture guidance makes the same point explicitly: an undocumented decision gets forgotten, inviting the same debate to be relitigated and changes that run against the original intent.2
2.3 In Contract Development, a Contract Boundary Is a Memory Boundary
For in-house development, “just ask that person” works for a while, but contract development adds a vendor change on top of staff transfers and departures. The moment the vendor who developed the system and the vendor maintaining it are different companies, whatever “why” lived in someone’s conversations and chat messages is gone completely.
From a contracting perspective, too, it’s entirely normal for development and maintenance to be separate contracts and separate phases (we covered this structure in our explainer on IPA’s “Model Transaction and Contract”). And under a quasi-mandate contract, precisely because the contracted party carries out the work autonomously, a record it can show the client of what was decided and how becomes the evidence backing that trust. An ADR helps on both fronts.
3. What Is an ADR
3.1 Nygard’s Proposal — Five Elements and a Two-Page Cap
ADR is the format Michael Nygard proposed in his 2011 blog post, “Documenting Architecture Decisions.”1 The main points are these.
- One file per decision. Number them sequentially, and never reuse a number
- Keep the file in a lightweight format like Markdown, inside the project’s repository
- Structure it around five elements: title / status / context / decision / consequences
- Status progresses from proposed to accepted, and when overturned, moves to deprecated or superseded. Never delete the old record
- Keep the whole thing to one or two pages, written in complete prose a future developer can read as if it were a conversation
Despite the word “architecture” in the name, this isn’t a technique reserved for large systems. If anything, this minimal fixed format works best precisely on small teams with no dedicated architect and no one assigned to documentation. ADR templates and tools are also organized systematically at the community site (adr.github.io), which is a good entry point for the idea of “recording an architecturally significant decision along with its rationale and trade-offs.”3
3.2 A Markdown Template
Here’s the minimal template I use on small projects, staying true to Nygard’s original format.
# ADR-NNNN: (State the decision in one short sentence)
## Status
Proposed | Accepted | Deprecated | Superseded (-> ADR-MMMM)
## Context
Why did this decision become necessary? Write the technical and business
assumptions, the constraints (budget, deadline, existing assets, the
customer's environment), and the alternatives you considered, in a way
a reader unfamiliar with the situation at the time can still follow.
## Decision
State it flatly, in the active voice: "We will do X." One to three sentences.
## Consequences
Write both what gets better and what gets worse (the trade-offs) as a
result of this decision. If there's a condition that would prompt
revisiting it in the future, note that too.
The key point is to write down the downsides too in Consequences. A decision with no trade-offs is barely worth recording. Microsoft’s guidance likewise stresses not hiding a decision’s consequences, whether intentionally or by accident, and that a record with no rationale loses its value over time.2
4. What to Write in an ADR, and What Not To
The single biggest reason ADRs stop happening is trying to write one up for everything. Microsoft’s guidance says to limit what you record to things that affect the system’s structure or an important quality attribute, and things that are hard to walk back.2 Translated into an everyday rule of thumb, that gives us the following table.
| Kind of decision | Example | Write an ADR? | Why |
|---|---|---|---|
| A technology choice that’s hard to change later | Making the database SQLite, using a file handoff for integration | Yes | Changing it later is costly, and touching it without knowing why is risky |
| Chosen from among several reasonable options | Generating a report with a library instead of COM automation | Yes | Knowing why the other option was dropped saves a successor from redoing the analysis |
| A constraint was the deciding factor | Giving up on auto-update because the customer’s environment is offline | Yes | It can be revisited once the constraint goes away (when the environment is refreshed) |
| An agreement with an external party | Matching the CSV’s character encoding and layout to the other party’s spec | Yes | Makes clear this is a boundary you can’t change unilaterally |
| Enforcing a convention or style | Naming rules, formatter settings, using-directive ordering | No | A config file like .editorconfig plus automation is enough |
| An implementation detail you can change any time | How internal classes are split up, how private methods are organized | No | The code and the code review are enough |
| Routine operational work | Bumping a library’s patch version | No | The change history (the commit log) is enough |
When in doubt, there’s a single test: would whoever looks at this code a year from now — including future you — want to ask why? If yes, write it up; if it’s self-evident from the code or the settings, don’t.
Another trap is thinking about the right granularity in terms of “what kind of document.” Deciding the division of labor up front, as below, removes the guesswork.
| Information you want to keep | Where it belongs | Relationship to the ADR |
|---|---|---|
| Why this approach was chosen | ADR | The main content |
| The current architecture diagram / data flow | A (thin) design document | Referenced from the ADR |
| The content of an individual change | A commit message / a PR | Linked by writing in the ADR number |
| Operating instructions | An operations manual | A different thing entirely (different readership). See The Basics of Writing a Word Manual for how to write one |
| A record of an incident response | An incident ticket / issue | If the response ends up changing the approach, write a new ADR for that |
5. Running ADRs on Small Contract Projects
5.1 Directory and File Naming
Carve out docs/adr/ right under the repository root, and name files with a sequence number plus a short slug.
docs/
adr/
0001-record-architecture-decisions.md
0002-use-sqlite-for-local-storage.md
0003-excel-report-via-com-automation.md
0007-excel-report-via-openxml-library.md
The standard move is making the very first entry an ADR about the decision to use ADRs at all. That way, a successor can understand the whole operating convention just by opening docs/adr/.
5.2 When to Write One, and Who Reviews It
- Write it the moment you’ve made the decision. As the closing step of a design discussion, turn the meeting’s conclusion into an ADR the same day. As covered later, batching them up to write later is a recipe for failure.
- Fold ADRs into the code review. All you check is whether a pull request touching an architectural approach includes an ADR addition or update. No separate ADR approval meeting is needed — folding it into the existing review is the realistic answer for a small team. Keeping ADRs under version control is also what Microsoft’s guidance recommends.2
- To overturn a decision, write a new ADR and change the old ADR’s status to
Superseded, cross-referencing the two. Never rewrite the body. Not editing an approved record, and preserving history through a chain of replacements — that’s what it means to treat an ADR as an append-only log.2
5.3 An ADR as a Deliverable You Share With the Client
In contract development, I recommend sharing ADRs with the client as part of the deliverables. There are three benefits.
- It becomes material for acceptance review and explanation. Instead of explaining verbally why the system is structured this way, you can just show the ADR. Since the client is a party to the constraints — budget, deadline, environment — that drove a decision, having it on record prevents a later mismatch in understanding.
- It’s insurance against a vendor change. From the client’s side, whether there’s a “history of decisions” to hand to the next vendor makes a huge difference to the cost and risk of a handover. We covered how to organize things before placing an order in What to Sort Out Before Outsourcing Windows App Development, but when deciding at contract time what documentation should survive after delivery, ADRs are among the highest-value-for-effort options.
- It pairs well with quasi-mandate reporting. A quasi-mandate contract requires reporting on how the work was carried out, and ADRs can be used directly as the report for a design phase.
5.4 A Realistic Sense of the Time It Takes
In my experience, writing one entry to the template takes 15 to 30 minutes. On a small project, decisions come up maybe a few times a month, so an investment of one to two hours a month preserves every single “why.” Compared against the time lost to investigation, re-litigation, and handover a few years down the line, there’s hardly a project where this doesn’t pay for itself.
6. Common Failure Patterns
| Failure pattern | Symptom | Countermeasure |
|---|---|---|
| Writing too much | ADRs get written for even trivial decisions, and the habit burns out in three weeks | Narrow the scope using Chapter 4’s decision table. A few per month is normal |
| A heavyweight template | A form with approval fields, impact analysis, and risk assessment that nobody actually fills in | Go back to just Nygard’s five elements. A one-to-two-page cap1 |
| Writing it in a wiki | Updates stop in a place separate from the code, drifts out of sync, and loses credibility | Keep it in the repository and review it together with the PR |
| Batching them up to write later | “I’ll write it once things settle down” -> the memory’s gone and you can’t | Write it right after deciding. If you can’t, write it live, screen-sharing, during the decision itself |
| Rewriting a past ADR | The history disappears, and you lose track of when the policy changed | Replace it with Superseded and keep the body immutable2 |
| Not writing the downsides in Consequences | It becomes a mere announcement, useless for reconsideration | Always write the trade-offs and the conditions that would prompt a revisit |
“Batching them up to write later” in particular is a trap you tend to fall into when introducing ADRs partway through an existing system’s life. Rather than trying to reconstruct every past decision, the realistic approach is to go back and write up just a handful of the major decisions you can still recall, then build forward from today’s decisions onward. Even on an existing (brownfield) system, it’s worth going back and recording whatever past decisions you can still reconstruct.2
7. ADR Worked Examples
Here are two full ADRs on subjects that come up often in small Windows business apps (the content is a generalized example).
The first is a classic technology-choice decision: the database.
# ADR-0002: Store business data in SQLite
## Status
Accepted (2026-07-17)
## Context
This system is a single-site inventory management desktop app. There are
two or three users, but in practice it's installed on one shared PC in
the back office and used in turns (only one person at a time). The
customer has no staff who could operate a database server on-premises,
and there's no budget for server hardware either. Data volume is
expected to stay in the low hundreds of MB even after ten years of
operation. We considered SQL Server Express, SQLite, and an Access file
(.accdb) as options. SQL Server Express was ruled out because the
customer has no ongoing capability to build and verify a server after
Windows Update runs. Access was ruled out due to the risk of corruption
under concurrent writes and its poor future migration path.
## Decision
We will use SQLite for data storage. The database file will not sit in
a shared folder; it will live locally on the main PC. Backups are taken
daily as a snapshot via VACUUM INTO, saved to the NAS (copying the live
file while the app is running is not an option, since it risks a
corrupted backup from a missed WAL file or a write race).
## Consequences
- Good: no database server to build or maintain. Backups are a single SQL statement
- Good: the runtime can be bundled with the app, keeping installation simple
- Bad: writes are locked at the database level, so this can't scale to multiple sites or many concurrent users
- Bad: migrating to a server database later will require a data migration and rework of the connection layer
- Revisit this decision the moment simultaneous use from multiple PCs becomes necessary (at that point, move to a server database or an API-based design)
The second is an example of overturning a decision already made. Pay attention to how Superseded is used here too.
# ADR-0007: Generate Excel reports with a library instead of COM automation
## Status
Accepted (2026-07-17) -- supersedes ADR-0003 (adopting COM automation)
## Context
There's a requirement to output invoices and monthly summaries as Excel
files. This was originally implemented with Excel COM automation per
ADR-0003, but an unattended nightly batch job repeatedly left Excel
processes hanging around and stalled processing, and requiring an
Office license on the execution machine became a recurring problem at
every device refresh. We considered continuing with COM automation
(adding process monitoring), switching to a library that generates the
Open XML format directly, and converting reports to PDF (a spec
change). PDF was ruled out because the client relies on being able to
add notes directly in Excel.
## Decision
We will switch reports to generating .xlsx directly with a library,
with no dependency on Excel itself. Formatting is kept as a template
.xlsx file in the repository, and generation works by populating cells.
## Consequences
- Good: Excel is no longer required in the execution environment, and unattended runs become stable
- Good: the process-leftover problem is eliminated structurally
- Bad: not all of Excel's features are available, so some existing report formatting has to be simplified
- Bad: turning the existing reports into templates takes rework effort
- ADR-0003 is marked Superseded, with a reference to this ADR
Just reading these two entries answers the exact questions that always come up during a handover: “why doesn’t this system have a server database?” and “why does the report code have leftover traces of launching Excel?” Together they run about 1,500 characters and take less than an hour to write.
8. Summary
- What causes trouble when it’s lost during maintenance and handover is not the What but the Why. An undocumented decision gets forgotten, inviting relitigated debates and changes that run against the original intent.2
- An ADR is a lightweight record format: one decision per file, five elements, one to two pages at most. Nygard’s original form works as-is for small-scale development.1
- Only write up decisions that are hard to change, that had real alternatives, or that a constraint decided. Leave conventions and formatting to automation — they’re out of scope for an ADR.2
- Keep them in
docs/adr/, and review them together with the pull request. Never overwrite a decision — replace it via Superseded — and keep the history immutable.12 - In contract development, an ADR becomes a deliverable that’s valuable to the client too, serving as acceptance-review documentation and as a handover document at vendor changes.
- Fifteen to thirty minutes per entry. Start by writing one for your very next design decision — and if you’re working on an existing system, start by going back and writing up just a handful of the major decisions you can still recall.
Related Articles
- How Should You Structure a Contract for Development and Ongoing Maintenance? — Choosing Between Quasi-Mandate and Contract for Work, Lessons From IPA’s “Model Transaction and Contract”
- What to Sort Out Before Outsourcing Windows App Development
- The Basics of Writing a Word Manual — Bad Examples and How to Fix Them
Related Consulting Areas
Komura Software LLC handles helping teams introduce ADRs as part of a design review, taking inventory of and documenting the design decisions behind an existing system, and building a maintenance setup with handovers and vendor changes in mind.
- Technical Consulting & Design Review
- Windows App Development
- Modification & Maintenance of Existing Windows Software
- Contact
References
-
Michael Nygard, Documenting Architecture Decisions. The original source for ADRs (2011). On the five elements — title/context/decision/status/consequences — the status progression from proposed to accepted to deprecated/superseded, the one-to-two-page length, keeping them as sequentially numbered files in the repository, and preserving old decisions via Superseded rather than deleting them. ↩ ↩2 ↩3 ↩4 ↩5 ↩6
-
Microsoft Learn, Maintain an architecture decision record (ADR). Guidance from the Azure Well-Architected Framework. On treating an ADR log as append-only and never editing an approved record; replacing a decision with a new record and cross-linking them when it changes; limiting scope to decisions that affect system structure or an important quality attribute and are hard to walk back; including context, rationale, trade-offs, and status (Proposed/Accepted/Superseded); undocumented decisions getting forgotten and inviting relitigated debate or changes against the original intent; and it being worthwhile to record past decisions retroactively even for an existing workload. ↩ ↩2 ↩3 ↩4 ↩5 ↩6 ↩7 ↩8 ↩9 ↩10 ↩11 ↩12 ↩13
-
adr.github.io, Architectural Decision Records. The ADR community site. On the definitions of an architectural decision (AD) and an architecturally significant requirement (ASR), on an ADR recording a single decision along with its rationale, trade-offs, and consequences, and on the collection of templates and tools available. ↩
Related Articles
Recent articles sharing the same tags. Deepen your understanding with closely related topics.
Incident Response Doesn't End at Recovery — A Postmortem (Recurrence Prevention) Template for Small Development Teams
Treating an incident as over once it's fixed and apologized for guarantees you'll repeat it. This article translates the blameless postmo...
Don't Forget to Decide 'How Many Seconds Is Fast Enough' — Organizing Non-Functional Requirements With IPA's Non-Functional Requirements Grade
Disputes like 'it's too slow' or 'we didn't expect that failure response' usually trace back to non-functional requirements nobody decide...
When You Inherit a System With No Source Code and No Documentation — A Practical Playbook for Keeping It Running
A practical playbook for starting operations and maintenance on a business system that has no source code and no specifications. Covers p...
When Not to Move a Windows App to the Web: A Decision Table and the Practical Answer of Splitting
Requests to move in-house Windows apps to the web are increasing, but for apps built around device integration, local file processing, of...
Windows App Outsourcing and Contract Development: What to Sort Out Before You Ask
Before commissioning Windows app outsourcing or contract development, here is how to sort out existing software modification, device inte...
Related Topics
These topic pages place the article in a broader service and decision context.
Windows Technical Topics
Topic hub for KomuraSoft LLC's Windows development, investigation, and legacy-asset articles.
Where This Topic Connects
This article connects naturally to the following service pages.
Windows App Development
We support Windows desktop applications that involve resident processing, device integration, operational logging, and maintainable structure.
Technical Consulting & Design Review
We help clarify design direction, architectural boundaries, lifetime ownership, and how to handle legacy Windows assets.
Frequently Asked Questions
Common questions about the topic of this article.
- What is an ADR (Architecture Decision Record)?
- It's a document that records a single decision affecting a software system's structure, in one file, using a short fixed format: title / status / context / decision / consequences. Michael Nygard proposed this lightweight format in 2011; the basic rules are to keep each one to at most one or two pages and commit it as Markdown in the same repository as the code. Unlike an exhaustive design document, it's specialized for preserving why a particular choice was made and which alternatives were discarded.
- What should I write in an ADR, and what can I leave out?
- What's worth writing up: decisions that are hard to change later (choosing a database or a communication method, the format of an external integration, and so on), decisions made between several equally reasonable options, and decisions where a constraint -- budget, deadline, existing assets -- was the deciding factor. Conversely, things a tool or convention can enforce mechanically, like naming rules or formatter settings, or things that are easy to change and self-evident from reading the code, don't need one. When you're not sure, use this test: 'would I, a year from now, want to ask why?'
- If I want to change a past decision, is it OK to rewrite the old ADR?
- No -- don't rewrite it; add a new ADR that replaces it. Change the old ADR's status to Superseded, add a reference to the new ADR, and leave its body untouched. Microsoft's guidance likewise recommends treating an ADR log as append-only and never editing an approved record after the fact. That way, the history itself -- of when and why the policy changed -- becomes a handover document in its own right.
- If we already have a design document, is an ADR redundant?
- They play different roles. A design document shows what the structure currently is, but it usually doesn't preserve why that structure was chosen and what was discarded. An exhaustive design document also tends to stop getting updated and drift away from the code after a few years. An ADR only requires appending a few hundred characters per decision, so it's much less prone to going stale -- even after the design document goes out of date, the reasoning behind each decision survives on its own. For small-scale development, a realistic setup is keeping the detailed design document thin and pairing it with ADRs.
Author Profile
Profile page for the article author.
Go Komura
Representative of KomuraSoft LLC
Focused on Windows software development, technical consulting, and investigations into failures that are difficult to reproduce.
Public links