Driving architectural decisions with a simple decentralized framework
This week’s issue provides a decentralized framework for making architectural decisions using simple practices, supporting a high-documentation / low-meeting culture.
So, let’s dive in.
In software engineering, the architectural decision-making process is a critical determinant of a system's success and adaptability. However, the rapidly advancing technological landscape challenges this process, which is characterized by increasing complexity and a need for agile responsiveness.
Architectural decisions shape our projects, making the technical vision and laying the groundwork for systems' long-term sustainability and adaptability. Those decisions can be as simple as choosing a code style to more important ones, such as which architectural style we select or which database type. After months of engineering, remembering the rationale behind a decision can be tricky because you need more context that influenced it.
One important aspect of this process to mention is the power of writing things down. Writing is a reflective process that reinforces your understanding. It forces you to break down complex concepts into simpler, understandable parts. This simplification clarifies your thinking, often leading to more efficient and elegant solutions.
Here, I present a simple framework that you can use to drive your architectural decisions in a decentralized way, with no single authority in charge. The main advantage of such a process is that we include more people in the software architecture process, which leads to a better spread of knowledge, making no single bottlenecks and improved motivation among the people.
It consists of the following three steps:
Recurring architectural discussions
Request for Comments (RFC) process
Architectural decision records (ADRs) creation
1. Architectural discussions
When we got the requirements as a team for some of them, if they were not straightforward or could impact important architectural topics in the project, we needed to discuss them first. For this, we can have a weekly or bi-weekly recurring conversation to discuss spikes, challenges, and decisions.
These discussions ensure continuous alignment between the architectural vision and the project requirements, effectively preventing problems in the future. They promote a culture of cross-functional collaboration, bringing together different perspectives from development, operations, security, and business, which improves the architectural approach with a holistic understanding of system lifecycles.
Yet, these sessions are invaluable for knowledge sharing, allowing team members to exchange insights, learn from one another, and stay aware of emerging trends and technologies. They also act as a proactive measure in risk mitigation, enabling the early identification and resolution of potential issues, thereby safeguarding the project against unexpected challenges.
The outcome of such discussion is usually:
We are suitable for this requirement, and there is no need to add anything. We go straight to the implementation and sometimes add an Architectural Decision Record (ADR) if documentation is missing.
We need to clarify more and do some deep research.
If the outcome is that we need to do more research, then we can create a spike that will allow us to start a Request for Comments (RFC) process.
2. Request for Comments (RFC) process
The RFC process is a procedure for harmonizing, enriching, and aligning architects' ideas and perspectives. In software engineering terms, it is comparable to a code review for design. With the RFC process, we attempt to address some difficulties when designing systems.
With RFCs, we create a shared context and spread the knowledge across the organization. We must ensure that everyone who reads the text comprehends the "why" and the "what” to give suitable comments. The "why" can be interpreted as why we are considering this in the first place and why this task is crucial to the company. The dimensions of the problem are the "what," or the problem you are trying to address with this design, and what you are expressly not doing.
The process consists of three steps: creation, feedback, and approval. It starts with creating a proposal, known as an RFC document, which details the proposed change in the software architecture. This document includes the rationale for the change, its expected impact on the system, and any other important information. The key here is ensuring the proposal is understandable to all stakeholders.
When the RFC is created, it is shared across the team or organization, effectively opening the possibility for a discussion period. This phase is crucial as it invites different perspectives and opinions, contributing to a complete decision-making process. Feedback received during this time may lead to revisions in the original proposal.
Following approval, the RFC is documented and integrated into the project's Architecture Decision Records (ADRs), serving as a valuable reference for the decision's context and rationale.
These documents have the following structure:
The usual fields are:
Summary - What is it about? Include the title.
Scope - Our scope with this RFC.
Participants - Who works on this RFC.
Status - In which status is it (proposed, commenting, decided).
Proposal - The document's core section details the proposed changes. It should be clear, detailed, and technical enough for readers to understand the implications. This can include diagrams, code snippets, or architectural patterns as needed.
Pros/Cons - An assessment of the potential impacts of the proposed changes. This includes technical implications on the system and possible effects on business processes, teams, and other organizational aspects.
Alternatives - This section discusses other options before arriving at the proposed solution. It shows that different approaches were evaluated and explains why the current proposal is preferred.
Open questions - Discuss other options before arriving at the proposed solution. This section shows that different approaches were evaluated and why the current proposal is preferred.
Conclusion - A summary of the RFC, reinforcing the key points and the value of the proposed changes.
Along with these fields, it can include some others, such as risks and mitigations, implementation plans, references, etc.
You can use different templates for RFCs, such as the Google one 📄.
In addition, in the proposal section of our Request for Comments (RFC) documents, we incorporate information from our:
Internal technology radar—This tool reflects our current technology landscape and offers an overview of the technologies, tools, and frameworks we are currently using, experimenting with, or planning to adopt. Referencing the tech radar in our RFCs ensures our proposals are compatible with our existing and future technology choices. Also, if you don’t have your own, you can use some industry-standard tech radars, such as the Thoughworks Technology Radar.
Established technical standards—The RFCs also adhere to our established technical standards, including guidelines for critical software development aspects like logging, exception handling, and testing. These standards represent our experience and industry best practices and serve as a guideline for our engineering efforts.
The Internet Engineering Task Force (IETF) maintains a comprehensive list of all the Request for Comments (RFCs) documents 📄 it has published from 1969. to 2023.
3. Architectural Decision Records (ADRs)
When we have a conclusion from the RFC document, we use those to create ADRs. ADRs are documents that capture decisions about a software system's architecture (introduced by Michal Nygard in 2011). They record the decision itself, the context in which it was made, the factors considered, and the expected impact. By providing a historical record, ADRs help communicate decisions to stakeholders, ensure consistency in decision-making, and promote transparency and accountability. Usually, we store it in the codebase, close to the issues they describe.
The ADRs are usually recorded in the following form:
ADRs usually have the following structure:
Title - A clear, descriptive title for the architectural decision.
Status - Indicates the current status of the decision (e.g., proposed, accepted, rejected, deprecated, superseded, etc.).
Context - This section explains the circumstances that led to the need for this decision. It includes the technical, business, or project constraints and requirements influencing the decision.
Decision - A detailed description of the decision being made. This should be clear and concise, often stated in a few sentences.
Consequences—Discuss the decision's outcomes, including the benefits and drawbacks. This section should cover how the decision will affect the system's current and future state, including its impact on scalability, maintainability, performance, security, and other relevant quality attributes.
You can use many templates for ADRs, yet I prefer this simple one 📄 by Michael Nygard.
Also, there are different tools you can use to view and track ADRs, such as ADR viewer.
To learn more about ADRs, check:
The Architectural Decision Records GitHub repo by Joel Parker Henderson.
A critical drawback with ADRs is that we tend to record ALL decisions inside, which is an anti-pattern. We want to record only architectural decisions and not make Any Decision Records.
Now, our architecture documentation structure could look like this:
When we finish the process, we can continue implementing our requirements while we have it thoroughly challenged with RFCs and document with ADRs.
Bonus: Take a look at my Heapcon 2023. talk where I presented this topic.
More ways I can help you
1:1 Coaching: Book a working session with me. 1:1 coaching is available for personal and organizational/team growth topics. I help you become a high-performing leader 🚀.
Promote yourself to 20,000+ subscribers by sponsoring this newsletter.