Jul 04, 2020

Documenting Design Decisions using RFCs and ADRs

If you work on a software project, no matter your role, you'll make and a lot of decisions and witness even more being made. Ranging from minor choices between code style A or B to rather impactful ones like where to store data, and why that should be the case. Recalling the reason behind a decision can be painfully hard after months of ongoing engineering, often because you're missing the context that led up to it.

Furthermore, the lack of documentation also makes onboarding and handover processes more difficult as you might find yourself struggling to explain decisions made in the past. Especially when teams are growing and a lot of progress has already been made previously, this will become strikingly obvious.

Luckily, as with most problems, there are plenty popular solutions to this, in this post, I want to focus on the process of discussing architectural design ideas using RFCs and making sure that decisions and their context stand the test of time using ADRs.

๐Ÿ™‹ RFCs: Discuss (Technical) Ideas as a team

When you stumble over a problem that gets in the way of building a feature, you spend time researching for known solutions, or try to get to one yourself (or even better, together paired up with a team member). Subjectively, your solution will always be the best it can be, which is completely fine for this stage. If you don't like it yourself, why would you go ahead and propose it to your team?

Sometimes, though, there will be one more piece of information that wasn't present at the time you thought about this issue, or a recent change turned things upside down. There can always be unknowns that will escape you, but that's where your team comes in!

Once you've collected all the information you want to propose to solve the problem, you can create a document containing the overall topic, the reason why you got there, and your suggested way of resolving it. You don't have to write a novel, focus on the relevant aspects and if there are potential alternatives you came across while researching, quickly explain why you didn't opt for one of those, as that will make it easier your team to reason about the area you attempt to cover.

This document, your Request for Comments (RFC), is at best placed close to where it will be used later on, for example in the same repository if it's related to code, or maybe even an existing location where your team stores and manages proposals. After your initial draft is ready to go, share it with your team!

The next step is the most important down the road, the discussion phase. Depending on the engagement or number of questions that come up you're able to guess the impact of your solution, which is another indicator you can use for planning. Most importantly, though, questions and feedback help to extend the RFC in ways you might not have considered before, sometimes even forcing you to step back and take another look at the problem, which can help in finding an even better solution.

To conclude, preparing, writing, and sharing RFCs with your team to review and iterate over the thought process that went into the proposal is an easy way to structure the R&D process.

๐Ÿ‘ ADRs: Write Down and Persist Decisions

Now that we've explored the steps from research over discussion up to deciding whether to adopt a proposal or not, we're entering the domain of Architectural Decision Records (ADRs in short).

As your team increases the number of significant architecture decisions, documenting those in a decision log gets more important as well. Whether it's for checking why a feature was built a certain way, or want to improve on previous decisions, keeping track of those is vital if you want to keep your velocity and scale the team. Especially when handing off tasks, the receiving person should be able to look up any past decision made, getting the necessary context.

As Michael Nygard put it in 2011, decisions that ยป affect the structure, non-functional characteristics, dependencies, interfaces, or construction techniques. ยซ should be stored in the project repository as lightweight Markdown files, numbered sequentially.

Another important property of decision records is that they're completely immutable. If there's ever a decision that obsoletes a previous one, you can go back to the prior decision and mark it as superseded, linking to the newer one. This way you preserve the history that might be useful in the future.

A popular template for decision records, which he suggested in the same post, each document should contain the following fields

Title

A concise title for the decision, e.g. Adopt Git repositories for version control. Should contain the most important part of what's decided on.

Status

The decision status, such as proposed, accepted, rejected, deprecated, superseded, etc.

Context

What is the issue that we're seeing that is motivating this decision or change?

The context should give information on the current situation that motivated this proposed decision, if you created an RFC earlier, this can be linked if you make sure this won't get deleted at any point, otherwise, it's safer to store that information in the decision record.

It's important that the context contains all relevant information at the point of writing, otherwise, you might miss crucial details later on when reviewing a decision that might have been agreed upon a long time ago.

Decision

What will be part of the change that we are proposing and/or doing?

Everything that changes as a part of this decision should come here. Once again, if you've written this down in any other document that will survive time, you can link to it.

Consequences

What becomes easier or more difficult to do because of this change?

This should include all benefits this proposal will yield and also any potential trade-offs you might have found while researching the solution.


This simple but effective structure allows us to document precisely the scope and outcome of each decision made. Of course, you can adapt it to any degree you like, or make customizations along the way, whatever works best for your team.

โš ๏ธ Pitfalls to avoid with written processes

Fully adopting new processes can take time and convincing. Especially when they include a lot of steps, or take up considerable amounts of time, the chance of success decreases.

And it's not different this time. When it takes too much work to write down suggestions as RFCs or decisions in documents, it's not very likely that everyone will commit to this. As we want every team member on board, we need to ensure that creating said documents involves as little friction as possible.

Following the aforementioned template will present clear guidelines of the way decision records should be written.

๐ŸŒ  The Possibilities are Endless

Once set up, you're ready to benefit from a versioned collection of decisions, which can be accessed at any time to answer the most important architecture-related questions.

With their full context preserved, previous decisions can be easily reviewed and improved upon once results are in.


I hope you enjoyed this post! If you've got any questions, suggestions, or feedback in general, don't hesitate to reach out on Twitter or by mail.