Skip to content
Howard van Rooijen By Howard van Rooijen Co-Founder
adr - A .NET Tool for Creating & Managing Architecture Decision Records

TLDR; Architectural Decision Records (ADRs) are a simple markdown based document for capturing the context, options, decision, and consequences of a decision. dotnet-adr is a .NET global tool for creating and managing ADRs. It allows you to create ADRs using a variety of templates, and to manage the ADRs in your repo. It's designed to be simple, flexible, and customisable. ADRs have made a huge positive impact to our software and data engineering processes, and we wholeheartedly recommend you adopt them too. You can install dotnet adr with the following command: dotnet tool install -g adr

Make Future You Thank Past You

Context drives intent, which manifests as code. This is the socio-technical contract of modern software development. If over time, code is the only remaining archaeological artefact, we are simply left with effect without knowing the cause.

Over the last decade we have found immense value in Gherkin based Executable Specifications to describe the behaviour (or intent) of a system; in fact the Gherkin (Specflow) feature files have often outlived the original code and have been used to re-implement the system using a more modern language or framework. They are also the secret sauce for providing RAG context to GitHub Copilot to more accurately generate code aligned with the intent of the system.

Now we have the code, and the intent, but we're still missing an artefact that captures the context. Architectural Decision Records (ADRs) fill this requirement exceedingly well. ADRs are simple text documents (our preferred format is Markdown) which précis some or all of the following aspects of a decision:

  • Context
  • Assumptions
  • Options
  • Rationale
  • Decision
  • Consequences

The 1st Law of Simplicity is "Reduce", and much like Bezos' infamous 6-page memo format, brevity is the key to the power of ADRs. Rather than a heavyweight functional specification, ADRs have much more in common with minutes from a meeting. The meeting may take hours, but reading the minutes, should take... minutes.

Good code comments don't explain what the code does, they explain what the developer was thinking when they wrote the code, what assumptions they were making, and what they were trying to achieve. This allows anyone reviewing the code to spot any faults with logic, assumptions that proved to be incorrect, or requirements which have evolved. ADRs operate on the same principle. Anyone can review the ADRs and quickly grok the context, the assumptions, the rationale, the decision, and the consequences, without being bogged down in detail.

With modern cloud native solutions, recording context takes on a nuanced significance; cloud services vary from IaaS to PaaS to SaaS, as a consumer you are not in control of the feature set, the scale characteristics, or the price point. When making an architectural decision you may be constrained by a missing feature, a financial budget, or a performance target. The speed of cloud innovation means that any of these constraints can change on a monthly basis. Keeping track of feature announcements and re-evaluating the context of previously made decisions is an engineering practice you should adopt as part of the ADR process.

The principles of ADRs are straightforward, but the implementation can be simple or as complex as your team or organization requires. The out-of-the-box default template is the Markdown Architectural Decision Records (MADR), but this tool and repo contains a number of alternative templates you can choose from, or you can create your own. If you want to read some real ADRs, check out these examples from our own OSS projects.

We find ADRs to be most effective when they are co-located with the code, in the same repo. We've worked on projects where "all documentation lives in Wiki / Confluence / SharePoint" because not all stakeholders have access to source control repos, but we find this approach to be high friction for all parties involved. This tool, adr, is designed to encapsulate our recommended practices.

Why we adopted ADRs

Several years ago we worked on a very complex project which required R&D, technical spikes, benchmarking, load-testing, performance tuning cycles, and further benchmarking in order to find the optimal solution. This process worked incredibly well and we delivered orders of magnitude performance improvements over the existing solution.

During the end-of-project retrospective we identified two sub-optimal outcomes; firstly we felt that while we had worked minor miracles in our technical solutions, the customer never seemed particularly impressed by the improvements. Secondly, the customer hired a new architect just as we finished delivering the solution, and as part of their onboarding process reviewed the solution and criticized almost every aspect with "I wouldn't have done it that way. At my last job we approached it like X and found it to be best".

We realized that the two issues were related. For the first problem, we concluded that we had failed to follow the most basic instruction you're given at school; "show your workings". We had hidden all the hard work, all the complexity, all of the hypothesis-testing experiments, and just presented the results Fait Accompli. The second problem had the same root cause. Because we had not recorded all of our experiments in a systematic way, we had no evidence to show that the approach the architect considered "best" was actually the first approach we took, but when we benchmarked and load-tested the approach it couldn't handle the data throughput at the price-point required by the customer. "Best" is entirely based on situational context. What's "best" in one situation is inappropriate in another.

We embrace evidence-based-decision-making as part of our experimental approach, and wanted to find a process that would allow us to document this in a formalized way. We did some research and discovered Architectural Decision Records. They have now become a fundamental part of our software and data engineering processes.

As a fully-remote organization, a secondary benefit from adopting ADRs has been how it allows us to enable distributed and asynchronous evidence gathering, discussions, decision making, and onboarding. This benefit manifests in a number of different ways; firstly, the process of drafting and evolving an ADR as a working group. Secondly, once the ADR reaches its "proposed status" it's very easy for senior decision makers to quickly grok the summary of the decision and provide input. Thirdly, any new contributor can get up to speed by using the collection of ADRs, AKA an Architecture Decision Log (ADL), to understand all the historical decisions that have been made, and most importantly what the situational context was at the point the decisions were made.

James Broome wrote a very nice introduction to Architectural Decision Records, which contains some useful tips based on our real-world experience.

Why create another ADR tool?

One of the reasons for "re-inventing the wheel" with adr when there are so many ADR tools already in existence, is that almost all of those existing tools are opinionated to the point of embedding the ADR templates into the tooling.

adr running in Windows Terminaladr running in Windows Terminal

Since we adopted ADRs in 2018, we've changed our default template a number of times (we've currently settled on MADR). Thus, with adr we wanted to decouple the tool from the templates, and make use of NuGet content packages as a mechanism to enable the ecosystem to build / use / share their own templates internally (using Azure DevOps or GitHub private package feeds), or publicly using nuget.org.

Getting Started

To install the adr global tool use the following command:

dotnet tool install -g adr

If you have previously installed adr and want to update to the latest version, use the following command:

dotnet tool update -g adr

adr templates package set <PACKAGE ID> - Sets the default NuGet ADR Template Package. Use adr.templates.

adr templates package install - Installs the latest version of the currently set ADR Templates Package.

adr templates set <TEMPLATE ID> - Sets the default ADR Template. The <TEMPLATE ID> can be obtained from adr templates show

Using adr

adr new <TITLE> - Creates a new Architectural Decision Record, from the current default ADR Template, from the current ADR Template package.

adr new <TITLE> -i <RECORD NUMBER> - Creates a new Architectural Decision Record, superseding the specified ADR record, which will have its status updated to reflect to point to this newly created ADR.

adr new <TITLE> -p <PATH> - Creates a new Architectural Decision Record, from the current default ADR Template, from the current ADR Template package, for the Architecture Knowledge Management (AKM) folder located at the specified path.

adr new <TITLE> -i <RECORD NUMBER> -p <PATH> - Creates a new Architectural Decision Record, for the Architecture Knowledge Management (AKM) folder located at the specified path, superseding the specified ADR record, which will have its status updated to reflect to point to this newly created ADR.

Configure the default ADR location in your repo

While adr is quite flexible in allowing you to specify were to create or update an ADR, either in the current directory, or by specifying a custom path using adr new <TITLE> -p <PATH>, sometime it's better to create a "pit of quality" and standardize the Architecture Knowledge Management (AKM) folder location for all users of the tool.

To support this requirement you can create a file in the root of your repo called adr.config.json which must have the following format:

{
    "path": "./Docs/Adr"
}

Where the value of path is relative to the root of the repo.

ADR Templates and ADR Template Packages

Example ADRs

It's always hard to write a document starting from scratch; this is why the default ADR templates contain guidance in the form of headings and notes. Real-world examples are always much more helpful, so below is a list of some publicly available ADRs from our Open Source projects. If you explore the repos, you can find more examples:

Which ADR templates are available out of the box?

We have collected a number of popular ADR templates and packaged them into the default template package.

NOTE: the status of the Open Source License for some of the templates is unclear. See each template for more details.

Alexandrian Pattern

ADR using the Alexandrian Pattern Language Approach coined by Architect Christopher Alexander et. al in 1977, which distils the decision record into the following headings:

  • Prologue (Summary)
  • Discussion (Context)
  • Solution (Decision)
  • Consequences (Results)

Source Joel Parker Henderson, see this issue about licensing.

Set as the default template using adr templates set alexandrian

Business Case Pattern

Emphasizes creating a business case for a decision, including criteria, candidates, and costs, created by Joel Parker Henderson, which distils the decision record into the following headings:

  • Title
  • Status
  • Evaluation criteria
  • Candidates to consider
  • Research and analysis of each candidate
    • Does/doesn't meet criteria and why
    • Cost analysis
    • SWOT analysis
    • Opinions and feedback
  • Recommendation

Source Joel Parker Henderson, see this issue about licensing.

Set as the default template using adr templates set business-case

Markdown Architectural Decision Records (MADR)

Architectural Decisions using Markdown and Architectural Decision Records, by Oliver Kopp, which distils the decision record into the following headings:

  • Title
  • Status
  • Context and Problem Statement
  • Decision Drivers
  • Considered Options
  • Decision Outcome
    • Positive Consequences
    • Negative Consequences
  • Pros and Cons of the Options
    • [option 1]
    • [option 2]
    • [option 3]
  • Links

Available as dual-license under MIT and CC0. You can choose between one of them if you use this work.

Set as the default template using adr templates set madr

Merson Pattern

An adaptation of the Nygard pattern, by Paulo Merson which adds the rationale behind the decision. It distils the decision record into the following headings:

  • Title
  • Status
  • Decision
  • Rationale
  • Consequences

Available under the MIT License.

Set as the default template using adr templates set merson

Nygard Pattern

A simple, low-friction "Agile" ADR approach by Michael Nygard, which distils the decision record into the following headings:

  • Title
  • Status
  • Context
  • Decision
  • Consequences

Available under CC0 1.0 Universal (CC0 1.0) Public Domain Dedication.

Set as the default template using adr templates set nygard

Planguage Pattern

A Quality Assurance oriented approach by John Terzakis, which distils the decision record into the following headings:

  • Title
  • Status
  • Tag
  • Gist
  • Requirement
  • Rationale
  • Priority
  • Stakeholders
  • Owner
  • Author
  • Revision
  • Date
  • Assumptions
  • Risks
  • Defined

Source Joel Parker Henderson, see this issue about licensing.

Set as the default template using adr templates set planguage

Tyree and Akerman Pattern

ADR approach by Jeff Tyree and Art Akerman, Capital One Financial, which distils the decision record into the following headings:

  • Title
  • Status
  • Issue
  • Decision
  • Group
  • Assumptions
  • Constraints
  • Positions
  • Argument
  • Implications
  • Related decisions
  • Related requirements
  • Related artifacts
  • Related principles
  • Notes

Source Joel Parker Henderson, see this issue about licensing.

Set as the default template using adr templates set tyree-ackerman

Custom ADR Templates and ADR Template Packages

You can create your own custom ADR Templates and Template packages, so that you can tailor them to your, your team's or your organisation's needs. For more information see the Custom ADR Templates and ADR Template Packages section of the dotnet-adr repo readme.

There is an example for adding your own 3rd Party template. If you do create your own NuGet template package please add dotnet-adr to the PackageTags element, so make it discoverable.

If you don't want to create a NuGet package, you can store the template file file inside the repository, and specify the TemplatePath in the adr.config.json file.

{
    "templatePath": "./Docs/adr-template.md"
}

Conclusion

If you want to make a small change to your team processes that can have a massive positive impact, we wholeheartedly recommend you adopt ADRs. Make Future You Thank Past You.

Howard van Rooijen

Co-Founder

Howard van Rooijen

Howard spent 10 years as a technology consultant helping some of the UK's best known organisations work smarter, before founding endjin in 2010. He's a Microsoft ScaleUp Mentor, and a Microsoft MVP for Azure and Developer Technologies, and helps small teams achieve big things using data, AI and Microsoft Azure.