Every software project includes a set of architecture decisions defining boundaries and constraints for further design and implementation.
It’s important to document those decisions somehow or else a development team might not know which decisions where made and with which assumptions.
Or they know the decision but are missing the context and the consequences and therefore decisions are blindly accepted or blindly changed.
In the following short tutorial I will show how to structure architecture decisions in so called Architecture Decision Records and how to manage them with a simple tool named ADR-Tools.

Architecture Decision Records (ADR)
The Agile Manifesto states that “Working software over comprehensive documentation” but this does not mean that there should be no documentation at all.
Especially for agile software projects where the architecture might adapt to new knowledge, market situations or technologies it is important to know what decisions were made, why they were made and with which assumptions.
The main problem with documentation is, that it needs to be close to the project and it needs to be short and concise or else it won’t be read or won’t be updated.
What are significant decisions that we should document in this scope?
According to my favorite author, Michael T. Nygard (Release it), significant decisions are those who affect the structure, non-functional characteristics, dependencies, interfaces, or construction techniques.
Therefore each record describes a set of forces and a single decision in their response, forces may appear in multiple Architecture Decision Records (ADR) and we store them in our project directory in doc/arch/adr-NNN.md and we number them sequentially and monotonically.
When reversing a decision, we keep the old ADR file but we’re marking it as superseded because it still might be relevant to know that there was such a decision.
The ADR file contains these typical elements:
-
Title: The ADR file have names consisting of short noun phrases, Example: ADR 1: Use Hystrix to stabilize integration points.
-
Date: The ADR’s creation date
-
Status: The decision’s status, e.g.: “accepted“, “proposed” (if stakeholders have not approved yet), “deprecated” or “superseded“
-
Context: A description of the forces at play (organizational, political, cultural, technological, social, project-local…)
-
Decision: The response to these forces, active voice, full sentences.
-
Consequences: The resulting context after applying the decision with all consequences, positive as well as neutral or negative ones.
For more detailed information, please feel free to read Michael T. Nygard: Documenting Architecture Decisions.
Of course other formats for ADRs exist, please feel free to visit https://adr.github.io/ for other tools and formats.
Installing ADR-Tools
We will be using ADR-Tools to manage our ADRs so we need to install it.
Using Mac, we may simply use the following command (using homebrew):
brew install adr-tools
Another choice e.g. for Linux is to download the latest release from GitHub here, untar the archive and add the src-path to your PATH.
ADR-Tools are a collection of bash scripts.
Initializing a Project
The first step is to initialize ADRs for our project (in this example it’s a typical Maven project).
We use adr init to initialize ADRs for our project within the specified directory …..
$ adr init doc/architecture/decisions
doc/architecture/decisions/0001-record-architecture-decisions.md
Afterwards, our project directory structure looks similar to this one:
├── doc
│ └── architecture
│ └── decisions
│ └── 0001-record-architecture-decisions.md
├── pom.xml
└── src
├── main
│ ├── java
│ └── resources
└── test
└── java
As we can see, a first decision already has been added to the project: It’s the decision to record our architecture decisions.
When opening the ADR file we’re able to read the following Markdown file:
# 1. Record architecture decisions
Date: 2018-05-26
## Status
Accepted
## Context
We need to record the architectural decisions made on this project.
## Decision
We will use Architecture Decision Records, as described by Michael Nygard in this article: http://thinkrelevance.com/blog/2011/11/15/documenting-architecture-decisions
## Consequences
See Michael Nygard's article, linked above. For a lightweight ADR toolset, see Nat Pryce's _adr-tools_ at https://github.com/npryce/adr-tools.
Creating new Architecture Decision Records
We’re ready now to create our first ADR. The command adr new allows us to create a new ADR with the given title.
$ adr new Use Hystrix to stabilize integration points
doc/architecture/decisions/0002-use-hystrix-to-stabilize-integration-points.md
This is what the generated Markdown file looks like:
# 2. Use Hystrix to stabilize integration points
Date: 2018-05-26
## Status
Accepted
## Context
Context here...
## Decision
Decision here...
## Consequences
Consequences here...
We’re adding another ADR:
adr new Use Thrift for data serialization between system a and system b
doc/architecture/decisions/0003-use-thrift-for-data-serialization-between-system-a-and-system-b.md
Listing Architecture Decision Records
We may list existing ADRs using adr list like this:
$ adr list
doc/architecture/decisions/0001-record-architecture-decisions.md
doc/architecture/decisions/0002-use-hystrix-to-stabilize-integration-points.md
doc/architecture/decisions/0003-use-thrift-for-data-serialization-between-system-a-and-system-b.md
Superseding a Decision
Now we will supersede a decision, for example if a new ADR supersedes our decision #3, we would type in the following command:
$ adr new -s3 Use Avro for data serialization between system a and system b
doc/architecture/decisions/0004-use-avro-for-data-serialization-between-system-a-and-system-b.md
This produces the following new ADR file with a reference to the superseded ADR.
# 4. Use Avro for data serialization between system a and system b
Date: 2018-05-26
## Status
Accepted
Supersedes [3. Use Thrift for data serialization between system a and system b](0003-use-thrift-for-data-serialization-between-system-a-and-system-b.md)
## Context
Context here...
## Decision
Decision here...
## Consequences
Consequences here...
Of course our old decision is changed, too including a reference to the new ADR and setting its status to “Superseded”.
# 3. Use Thrift for data serialization between system a and system b
Date: 2018-05-26
## Status
Superseded by [4. Use Avro for data serialization between system a and system b](0004-use-avro-for-data-serialization-between-system-a-and-system-b.md)
## Context
Context here...
## Decision
Decision here...
## Consequences
Consequences here...
Generating Graphs
To gain an overview of our ADR’s relations we may generate a graph in the DOT format using adr generate graph like this:
$ adr generate graph
digraph {
node [shape=plaintext];
_1 [label="1. Record architecture decisions"; URL="0001-record-architecture-decisions.html"]
_2 [label="2. Use Hystrix to stabilize integration points"; URL="0002-use-hystrix-to-stabilize-integration-points.html"]
_1 -> _2 [style="dotted"];
_3 [label="3. Use Thrift for data serialization between system a and system b"; URL="0003-use-thrift-for-data-serialization-between-system-a-and-system-b.html"]
_2 -> _3 [style="dotted"];
_3 -> _4 [label="Superceded by"]
_4 [label="4. Use Avro for data serialization between system a and system b"; URL="0004-use-avro-for-data-serialization-between-system-a-and-system-b.html"]
_3 -> _4 [style="dotted"];
_4 -> _3 [label="Supercedes"]
}
We may write this output to a file e.g. adr generate graph > generated/graph.dot
From this DOT file we may create an image e.g. using GraphViz like this:
dot -Tpng generated/graph.dot -ogenerated/graph.png
Another choice is to use an online tool like webgraphviz here so you don’t need to install another tool.
This is what the generated graph looks like as png-image:

Generating Table of Contents
To include the ADRs in other documents we may generate a table of contents for our ADRs using adr generate toc like this:
$ adr generate toc
This returns the following Markdown code:
# Architecture Decision Records
* [1. Record architecture decisions](0001-record-architecture-decisions.md)
* [2. Use Hystrix to stabilize integration points](0002-use-hystrix-to-stabilize-integration-points.md)
* [3. Use Thrift for data serialization between system a and system b](0003-use-thrift-for-data-serialization-between-system-a-and-system-b.md)
* [4. Use Avro for data serialization between system a and system b](0004-use-avro-for-data-serialization-between-system-a-and-system-b.md)
Linking Architecture Decision Records
When ADRs are linked somehow we want to document this and adr link eases this for us.
Let’s use an example where ADR #4 amends ADR #2 so that we could link both with the following command:
$ adr link4 Amends 2 "Amended by"
Now our graph looks like this:
adr generate graph
digraph {
node [shape=plaintext];
_1 [label="1. Record architecture decisions"; URL="0001-record-architecture-decisions.html"]
_2 [label="2. Use Hystrix to stabilize integration points"; URL="0002-use-hystrix-to-stabilize-integration-points.html"]
_1 -> _2 [style="dotted"];
_2 -> _4 [label="Amended by"]
_3 [label="3. Use Thrift for data serialization between system a and system b"; URL="0003-use-thrift-for-data-serialization-between-system-a-and-system-b.html"]
_2 -> _3 [style="dotted"];
_3 -> _4 [label="Superceded by"]
_4 [label="4. Use Avro for data serialization between system a and system b"; URL="0004-use-avro-for-data-serialization-between-system-a-and-system-b.html"]
_3 -> _4 [style="dotted"];
_4 -> _3 [label="Supercedes"]
_4 -> _2 [label="Amends"]
}
Or as an image:

In addition both ADR files were updated:
ADR #2 now looks like this one:
# 2. Use Hystrix to stabilize integration points
Date: 2018-05-26
## Status
Accepted
Amended by [4. Use Avro for data serialization between system a and system b](0004-use-avro-for-data-serialization-between-system-a-and-system-b.md)
## Context
Context here...
## Decision
Decision here...
## Consequences
Consequences here...
ADR #4 has been changed to this:
# 4. Use Avro for data serialization between system a and system b
Date: 2018-05-26
## Status
Accepted
Supercedes [3. Use Thrift for data serialization between system a and system b](0003-use-thrift-for-data-serialization-between-system-a-and-system-b.md)
Amends [2. Use Hystrix to stabilize integration points](0002-use-hystrix-to-stabilize-integration-points.md)
## Context
Context here...
## Decision
Decision here...
## Consequences
Consequences here...
Alternatives
Other alternatives as tool or syntax/format exist. There are even tools where you write the decisions as Java annotations in a class (not sure if I like it)…
Y-Statements – Sustainable Architectural Decision Records
Markdown Architectural Decision Records (MADR)
More information: InfoQ
e-adr
Documentation via Java annotations: GitHub
Tutorial Sources
Please feel free to download the tutorial sources from my GitHub repository, fork it there or clone it using Git:
git clone https://github.com/hascode/adr-examples.git