Recording Architecture Decisions as ADRs: With AI Support and Without Maintenance Debt
A practical guide: keep architecture decisions as Markdown ADRs in the repository, use language models for drafting, comparing alternatives and spotting gaps, leave responsibility with the team, and avoid staleness by superseding records instead of maintaining them.
A developer suggests in a chat that the team switch its message queue. Two colleagues agree, a ticket is created, the code changes. A year later, a new team member asks why the system does not run the product that the rest of the organization uses. Nobody remembers exactly. The chat is archived, the ticket contains only the work order, and the person who tipped the balance back then has left the company.
Scenes like this are the norm, not the exception. Architecture decisions emerge in everyday work: in meetings, in comments on code changes, in chats. What is missing is a place where context and rationale end up. Architecture Decision Records, or ADRs for short, are an established means for this. This guide describes how to keep them as Markdown files in the repository, how language models help with drafting, and how to avoid creating yet another piece of documentation that nobody maintains after six months.
The problem: decisions get lost
Michael Nygard described the pattern in a blog post in 2011, which is still regarded as the origin of the ADR idea. His observation: large architecture documents do not solve the problem, because "Nobody ever reads large documents, either." They are written once, rarely read, and go stale because every change to the system requires a manual change to the document.
Nygard names two typical reactions when the rationale is missing. Either the team accepts a decision blindly, even though circumstances have changed. Or it changes the decision blindly, without understanding which problem it originally solved. Both cost something, just at different points in time.
The Institute for Business Informatics at JKU Linz notes in a project description that keeping documentation up to date remains one of the challenges and that ADRs still have to be created manually. This is exactly where support from language models comes in: not at deciding, but at writing things down.
What an ADR should achieve
The MADR project defines an architecture decision as "a justified software design choice that addresses a functional or non-functional requirement of architectural significance". Two words matter here: justified and significant. An ADR records exactly one decision and explains why it was made.
Nygard's minimal form has five sections: title, status, context, decision and consequences. According to Nygard, the whole document should be one to two pages long. The MADR template, currently in version 4.0.0 of September 17, 2024, extends this with decision drivers, considered options and their pros and cons. In practice, this extended form works well because it forces the team to name alternatives at all.
Not every decision needs a record. Use three questions to check whether a decision is architecturally significant:
- Does it affect the structure of the system, that is, boundaries, interfaces, data flows?
- Does it influence a key quality attribute such as security, availability, maintainability or cost?
- Is it hard to reverse because data would have to be migrated, contracts have been signed, or several teams would have to switch?
If at least one question applies, write an ADR. If none applies, a comment in the code or in the ticket is enough.
Storage in the repository, versioned with the code
The repository is the place where the source code lives together with its change history. ADRs belong there because they then go through the same review and approval path as the code itself. JKU Linz accordingly describes ADRs as Markdown files with a predefined structure that are stored as part of the repository and managed together with the code.
Here is how to set up the storage:
- Create a fixed folder, for example
docs/adr/. One folder per repository, not per team. - Number the files sequentially:
0001-postgresql-as-primary-database.md,0002-events-via-message-queue.md. A number is never reused. - Keep a template as
0000-template.mdso that nobody has to invent the structure. - Introduce every ADR through a pull request, that is, the usual proposal of a code change that others review and approve before it is merged. Ideally, use the same pull request as the code that implements the decision.
- Maintain an index file
README.mdin the folder that lists the number, title and status of every record. A small script can generate this list.
One basic principle is essential: records are not overwritten. The Azure Well-Architected Framework puts it this way: "The ADR serves as an append-only log. Don't go back and edit accepted records. If a decision changes, write a new record that supersedes the original and link the two together." The status makes the current state visible: Proposed, Accepted, Superseded by ADR-NNNN, Rejected.
AI support: draft, alternatives, gaps
A language model, often called an LLM for Large Language Model, produces a text as output from a text input. This is useful for ADRs because the raw material of a decision usually already exists as text, just scattered: in chat histories, meeting notes, tickets, comments. Three uses work well in practice.
Draft from raw material. Copy the relevant chat history, the ticket and your notes into a request and let the model create a draft in your template. A workable instruction reads: "Create an ADR from the following notes using the attached template. Do not invent facts. Where information is missing, write OPEN in square brackets and state what is missing." The last sentence is important. Without it, the model fills gaps with plausible-sounding assumptions.
Comparison of alternatives. Have the model list the considered options with pros and cons in relation to your decision drivers. The result is a basis for discussion, not a verdict. The team adds options that are missing, strikes arguments that do not apply to its own context, and corrects claims about products that the model draws from outdated knowledge.
Gap detection. Give the model the finished draft and ask it for follow-up questions: Which assumptions are not stated? Which consequences are missing? Under which conditions would the decision have to be reversed? Who is affected but not mentioned? A model can usually answer these questions in a useful way because they are structural and require no knowledge of the specific system.
The limit is empirically documented. In 2024, Dhar, Vaidhyanathan and Varma investigated in an exploratory study whether language models can generate architecture decisions. Their finding: models such as GPT-4 produce relevant and accurate design decisions, but these "fall short of human-level performance". Further research is needed to reach human level.
Two caveats belong here. First, the study is from March 2024, and models have continued to develop since then; the specific quality gap of that time is a snapshot, not a law of nature. Second, the same applies to this guide: the split between the work you give to the model and the work you keep for yourself shifts with every model generation. What follows is not waiting, but a process rule that is independent of model quality: a model's draft is a basis for review, not a result. This rule remains sensible even as drafts get better, because it defines responsibility and not capability.
Responsibility stays with the team
An ADR documents a decision that people have made and stand behind. Three rules help keep this clear even with AI drafts.
First: every ADR names a responsible person or body as well as the people involved. Who carries the decision is stated in the record, not only in the commit history.
Second: an AI draft has the status Proposed and stays there until people have reviewed and adopted it. A model's output is not a resolution. Only approval in the pull request by the named owners sets the status to Accepted.
Third: mark the origin. A short note at the end of the record is enough, for example: "Draft by language model from ticket 4711 and chat history of March 12, reviewed and extended by M. Berger and T. Nowak." Later readers can then judge how the text came about and know whom to contact with questions.
The Azure Well-Architected Framework adds a point that is especially easy to lose with AI drafts: "Always include context and rationale. A record without justification loses its value over time." A model can derive context only from what it is given. If the rationale is missing in the raw material, it is also missing in the draft, or worse, it is invented. The review must therefore always ask: does this really state why the team decided this way?
Working without maintenance debt
Maintenance debt arises when documentation demands work that nobody has planned for. ADRs avoid this through four decisions that you should make deliberately.
No retrofitting of the backlog. Start with the next decision that is due anyway. Reconstructing the existing backlog is tempting, but expensive and often speculative. If an old topic comes up again because it is to be changed, write an ADR at that point that describes the previous state as context.
Supersede instead of change. An outdated ADR is not a maintenance case. It gets the status Superseded and a link to the new record. The old one stays in place because it explains why the system looked the way it did for a while. Nobody has to check old texts for currency.
Creation in the usual workflow. The AI draft lands directly in the pull request, together with the code. The review happens where the team reviews anyway. A separate documentation tool with its own login and its own approval creates a second review path that hardly anyone follows in practice.
No design guides. The Azure Well-Architected Framework explicitly advises: "Avoid making decision records design guides." An ADR describes the decision, not the instructions for implementing it. Supplementary documents are linked, but the record must remain understandable without them. Otherwise it goes stale with every linked document.
Introduction in four steps
- Define the template. Take the MADR structure or Nygard's minimal form and adapt it once. Add fields for owners and origin. After that, do not change the template for a year.
- First three decisions. Choose decisions that are due in the coming month anyway. Have the language model create the draft, review it together and submit it by pull request.
- Standardize the follow-up prompt. Store the instruction for gap detection in the repository so that every team member asks the same review questions. Re-check the prompt with every model change, because what a model does on its own changes faster than the template.
- Evaluate after three months. Check whether the records are read, whether new team members find them, and whether the review in the pull request actually takes place or is merely waved through.
Appendix: template and example
The template follows MADR and adds fields for responsibility and origin:
ADR-NNNN: Title as a statement
Status: Proposed | Accepted | Superseded by ADR-NNNN | Rejected
Date: YYYY-MM-DD
Owner: Name or body
Involved: Names
## Context and problem statement
What is the situation, which problem has to be solved?
## Decision drivers
- Driver 1 (for example operating costs, existing knowledge in the team)
- Driver 2
## Considered options
- Option A
- Option B
## Decision
Option A was chosen because ...
## Consequences
- Positive: ...
- Negative: ...
- Reversal condition: If ..., the decision must be reviewed.
## Pros and cons of the options
For each option: good, because ... / bad, because ...
## Origin
Draft by language model from ..., reviewed by ...
A shortened example shows how concise a record can be:
ADR-0007: Events between services via the existing message queue instead of direct HTTP calls
Status: Accepted
Date: 2026-10-14
Owner: Platform architecture group
Involved: M. Berger, T. Nowak, S. Yilmaz
## Context and problem statement
Three services call each other synchronously. If one fails, the others block. Order processing was affected twice in September.
## Decision drivers
- Resilience of order processing
- Existing operational knowledge of the queue in the team
- No additional infrastructure
## Considered options
- Keep direct HTTP calls with retry logic
- Events via the queue that is already operated
- Introduce a new streaming platform
## Decision
Events via the existing queue. It is already running, the team knows how to operate it, and decoupling solves the blocking problem.
## Consequences
- Positive: Services remain operational when a neighbor fails.
- Negative: Data between the services is only eventually consistent; the order of events must be handled in the consumer.
- Reversal condition: If throughput permanently exceeds the capacity of the queue, the introduction of a streaming platform must be reassessed.
## Origin
Draft by language model from ticket PLT-412 and chat history of October 9, reviewed and extended with the streaming option by M. Berger.
What remains
The division of labor is simple to describe: the language model structures, compares and asks follow-up questions. The team decides, reviews and takes responsibility. The repository records what was decided and why, in the same history as the code. Staleness is not fought but replaced by new records.
What remains open is what the sources used do not establish: how much time AI support saves in a specific team, and whether the records are actually read when it matters. Both can only be tested in your own organization. And the boundary between what you leave to the model and what you write yourself will shift; this guide is a snapshot from October 2026. What should remain is the part that does not depend on model quality: a template, a folder in the repository, a named owner, and the next decision that has to be made anyway.
Frequently asked questions
- Which decisions belong in an ADR and which do not?
- An ADR is worth writing for decisions that affect the structure of the system, influence a key quality attribute such as security, availability or cost, or are hard to reverse, for example because data would have to be migrated or several teams would have to switch. If none of these three conditions applies, a comment in the code or in the ticket is enough. This selection keeps the number of records small and the collection readable.
- May a language model write an ADR?
- It may write the draft, but it must not make the decision. A model can structure notes, chat histories and tickets into the agreed template, list alternatives with pros and cons, and ask follow-up questions about missing assumptions or consequences. A 2024 study shows that such drafts are relevant but not at the level of human experts. The draft stays in the status Proposed until named owners have reviewed it and approved it in the pull request.
- How do you prevent ADRs from going stale and becoming a maintenance chore?
- Accepted records are never overwritten. When a decision changes, a new record is created, and the old one gets the status Superseded and a link. Three more rules apply: do not retrofit the existing backlog, create and review records in the normal pull request workflow instead of a separate tool, and keep design guides out of the record so that it does not age with every linked document.