Collaboration is the most essential part of the architecture. More people in the room will produce more alternatives, challenge each other, and end up with better results in the long run. It also doesn’t matter if we get it right when there is not enough buy-in. A collaborative nature should intertwine all stages: thinking, feedback, implementation, documentation, and reflection (which could lead to revision). Decision records helped me improve teamwork and transparency in these areas over the years. Documentation and historical context happen as a “side effect”. This method is so effective and lightweight that non-engineering departments in a company started using it independently, without any guidance.

Before we had decision records

Being in a remote-first company, chat is the usual place for conversations. In its depths, there are thousands of ideas. Architecture topics are oftentimes brought up as well. We also had our share of meetings where engineers discussed and presented their visions. Within non-remote companies, the same thing happens, but in different forms, like by-the-kitchen discussions.

All of these suffer from lack of transparency*, unchecked bias, lack of full context, and reliance on individuals. From my experience, getting invited midway through is a mess when a discussion happens in one of the aforementioned formats. It is often hard to understand the full context, as quick responses promote mental shortcuts and many assumptions. Bias is hard to identify because everything is flowing fast, and some decisions have already been made in the other thread. Half of the content lives in one person’s head or in poor-to-consume format. We’re lucky if half of it doesn’t get forgotten. I’m not any better myself: Going through some of my old conversations on Slack is quite a trip. I do not know what I meant or how anyone else did. The issue is with these tools: they are great only to start a discussion.

The next phase was, of course, keeping our architecture documented. This vague statement probably meant up-to-date, book-like write down of architecture, with diagrams and whatnot. Euphoria didn’t last long. Large documents are hard to create, update, and read - the less up-to-date it is, the fewer people reference them, the fewer folks keep them up-to-date. Oh, well.

We needed something lighter. This is where I stumbled upon decision records on Martin Fowler’s website.

* Chat could be argued as transparent, but discussions often happen in random places. You have to know that this specific conversation happened in this specific channel (because a new customer raised an issue, and all of a sudden, on-duty engineers are deep into discussing better cross-server communication patterns). That is if it wasn’t a private channel.

Decision records don’t replace wikis. Maintaining a wiki is more challenging, but it might be a good idea for core concepts, which don’t change often. In our case, some decision records “graduate” to the wiki.

Decision records

The decision record is a list of documents, with pending and taken decisions. It is very simple, making it easy to keep up. The barrier to entering is low, which encourages everyone to participate. Transparency is baked in.

There are three primary purposes (which also happen to be stages through which each decision goes through):

The first one is the thinking tool. We think deeper by trying to explain the problem, proposing a solution, and writing down discarded options. The longer form allows us to verify and reconsider our ideas. It helps keep our thoughts concise and, hopefully, easier to understand.

The second one is the collaboration facilitator. We’re writing it to help others and get feedback from them. The form encourages reading, researching, and thinking through the problem. It doesn’t discriminate against people who are too shy or slow to speak up. It is more inclusive for folks with disabilities (like hearing impairment).

The last one is the archive of decision rationale. We can make better decisions by understanding how we got to where we are. Reflecting on the good and bad is easier when we have a more objective log of decisions rather than a vague memory of them. The same conversations are not brought up over and over again unless there is a new and significant point that would undermine a decision taken. New developers can learn what decisions were taken, how they were picked, and why the others were discarded.

Applied in practice

The process between companies will look different. However, there are a few sections which should always be present. (In this or other format.)

The first three sections - title, context, and status - should also be viewed as TLDR (Too Long, Didn’t Read). A developer skimming through a long list of decisions will not thoroughly read each one of them. They should be able to get the gist from only these sections.

Example template in Notion.

Title

The title allows for easy identification of what the decision is about. Focus on the problem we’re trying to solve rather than the solution we would like to prescribe.

Context

The context should describe the problem we’re trying to solve, why it is crucial, and our current situation. It sets the stage for possible solutions - we can specify their advantages and disadvantages rather than use “it depends”. This is very useful when we have to revisit decisions that have already been taken. What used to be a good decision often has to be revisited due to changed context. For example, weighting non-functional requirements, like security, will change as our software goes through different stages of growth.

Status

Is this decision record still a draft, pending approval, approved, or implemented? Marking a decision as stale or needing revisiting will alert the reader. A good practice is giving each status short context:

Approved decisions should have a summary of what we agreed to. Until it is implemented, the next steps should be stated. It’s an excellent place to mention our immediate plan and what will be implemented later.

Once implemented, keep track of consequences. Be honest, and don’t skip the bad ones. This is a great feedback loop of how we’re doing. It will naturally become a short summary of “why” once the decision has been revisited.

Involved people

Except for the author (who is expected to be a driver), we found it a good idea to mention who we would like to receive an opinion from. While the core idea is to be open to everyone, mentioning a few key people directly increases the chances of getting their perspective. We might be looking for someone with plenty of experience in a given area (for example, database security). Or we might want to ensure that people who will be affected the most are (mostly) happy with the new approach (for example, aligning how micro-services communicate). Personally, I try to assign at least one person who is most likely to have a different opinion.

Proposal

This section should clearly explain the main option we’re considering. If possible, we should supply proof of concepts, benchmarks, and/or diagrams. We should ensure that we list trade-offs - no free lunch exists. Good decisions will have negative consequences as well.

Different options

All options which we went through should be present on a decision record. Not only the leading contenders but also the ones we discarded. This shows our readers that we did think through other ways of solving the problem.

The lack of this section is a tell-tale sign that the author didn’t go deep enough or they did not confront their bias. It doesn’t mean the proposed option is wrong, but we should not proceed with the first “this sounds right”.

High-level ideas

No matter how we structure decision records, there are a few key ideas that we should keep in mind:

Transparency and honesty

It is fine not to have all of the answers. It is not acceptable to keep that knowledge from the reader. We might be tempted to skip it, especially when we think it is irrelevant. Don’t. Readers will appreciate it. On occasion, it might turn out to be a lot more critical than we thought.

In one of the decision records, I wrote that I did not test foreign keys to inherited PostgreSQL tables. At the time, I didn’t know it was not possible. It helped a more knowledgeable person catch this mistake early. (We could argue that not testing it was a more significant mistake, but that was a complex decision and a long week. Stuff happens. Be honest.)

Confronting bias

We all have our biases. Most likely, even before starting a decision record, we have a solution in mind. We will feel the pull towards it through most sections.

The first pull will happen when we scribble the title: What should be “Securing tenant data” becomes “Row Level Security”. (The second title is fine if we have already decided on RLS in another decision record and want to discuss its implementation details.)

Explaining the context also can get tricky. It is easy to focus on our favorite solution and write down the perfect scenario for it as a context. I once focused on localization when there were no plans to go to more countries within the next few years! Yes, all things being equal, it would be great to have the capability. But we should be honest about what is essential and what the causes and symptoms are.

Having a single solution is usually a clear sign of our bias. In the same vein, be wary of “dummy options” - technically, a different solution is listed, but it is feeble or doesn’t fit the given context. That’s just a single solution disguised.

If we don’t have a better idea, we can always fall back on honesty and disclose our biases upfront to the reader.

Years of writing decision records, and I still make mistakes like these. (If you can’t spot it: does it have to be in a separate table?)

Clarity

It is our responsibility to keep the document short and focused. One decision record, one problem. Time and attention are limited resources. It should get us more and quicker feedback. I’ve written long and unfocused decision records where the main point was totally lost on the reader. What helps me is letting a finished record sit for a day so I can read it fresh. (That’s what I do with articles as well!)

Remember that by virtue of writing down, we are deeply submerged in the problem space. We should be conscious of our “curse of knowledge” - what is obvious to us might not be obvious to others.

“If I had more time, I would have written a shorter letter.” Blaise Pascal

Be open to feedback

We’re not writing a decision record to show off skills. We want to get valuable feedback. Be open to feedback and different solutions.

Takeaways

  • Use decision record as a tool for thinking, collaborating, and archiving “what and why”.
  • Each decision should have a clearly defined problem, context, proposed solution, and competing options.
  • Focus on the clarity of the proposed solution.
  • Be honest and transparent about what is missing and what our biases are.

Further reading