Architectural decision records (ADRs)

Architectural decision records (ADRs)

Do you remember everything you did last week? No? Neither do we. This is why it’s important to document stuff—especially the important stuff.

“Why is more important than how”, the second law of software architecture. So we need to identify not just the decision we made, But the reason we made it. As a solution for this we can use ADRs to record such decisions because it gives us a specific template to work with.

An ADR as a simple document that describes a specific architectural decision we made. We write one ADR for every architectural decision we are going to make. Over time, they’ll build up into an architectural decision log.

Writing ADRs

Title

ADR starts with a Title. Title is used to describe the decision we got. Craft this title carefully. It should be meaningful, yet concise. A good title makes it easy to figure out what the ADR is about. It should describe what the ADR is about, much like the headline of a news article or blog post, and which is especially useful when you’re frantically searching for an answer.

What is about this Three Digit Number?


ADRs title will start with a three digit number, with leading zeros if needed. This number allows you to number your ADRs sequentially, starting with 001 for your first ADR, all the way to 999. Every time you add a new ADR, you increment the number. This makes it easy for anyone reading your records to know which decisions came before others.
Note: Every ADR should get a unique identifier therefore we can’t reuse an ADR number.

Status

The status communicates where the team stands on the decision itself. So there are different statuses an ADR can have.

1. Request for Comment (RFC)

We use this status for ADRs that need additional input—perhaps from other teams or some sort of advisory board. When an ADR in RFC status is typically a draft, open for commentary and You ask everyone to respond to critique from anyone invited to do so.
Make sure that RFC status should always have a “response by” deadline.

2. Proposed

After everyone has a chance to comment, the ADR’s status moves to Proposed. This means the ADR is waiting for final approvals. ADR will soon be moved to either Accepted (approved and ready for implementation) or Rejected (not moving forward with the proposal) after a final decision is made.

3. Accepted

A decision has been made, and a cool outfit! Everyone is on board who needs to be. Accepted status also tells the team tasked with implementing this decision that they can get started.

There is one more status we need to be aware of: Superseded.

4. Superseded

We have arrived at a decision, which we diligently record in an ADR. Signed, sealed, delivered we’re done. But! In the Software Development world everything is changing.

Whatever the reason, the decision you made is no longer appropriate. What now?

In this situation we have to write another ADR, with that the old ADR will be Superseded by the new one.

Context

Context matters. Every decision you’ve ever made, you made within a certain context and with certain constraints. This is the place where we explain the circumstances that drove us to make the decision the ADR is capturing. Also this section needs to have any and all factors that influenced your decision.

Usually the context section answers the questions like `Why did we have to make a choice to begin with ?? ` But make sure we do not describe our decision just yet!That will be included in the Decision Section.

Example:

Decision

Even if the ADR is in the RFC or `Proposed` status and the decision has not been made yet. Even that this Decision section can start by clearly expressing the decision being made. In this section is the place where we are going to explain why we’re making the decision which we mentioned. By doing this in future you or anyone else who is going to read the ADR. will be able to understand not just the decision but also the justification of it. For more readability and understanding the concepts we can add diagrams explaining our decision and its effects.

Consequences

In Software development everything has a trade-off, which means every decision has some kind of `Consequences` . Therefore it is really important to identify the good and bad of architectural decisions and document those consequences. By doing this we can improve the transparency of the software by ensuring that everyone understands what the decision entails, including the team(s) affected by it. Architectural decisions can affect all kinds of things—teams, infrastructure, budgets, even the implementation of the ADR itself.

Another important thing is `Collaborating with others`, this is also a great way to make sure that our assessment is thorough. No matter how hard you think through the consequences of the ADR, you’re likely to miss a few things; remember multiple perspectives will reveal more potential consequences.

Governance

Okay, Now we have spent a lot of time analyzing trade-offs and writing an ADR to record the decision. Now we need a way to ensure that the decision is correctly implemented. That is the Job of the `Governance` section. Here we can use manual techniques like pair programming or code reviews, or automated means like specialized testing frameworks.

Notes (Closing Notes)

The Notes section contains metadata about the ADR itself.

Example:

001: Fetch and Store API Response in Google Cloud DataStore for Webhook Events


Status: Approved


Context:

Currently, the webhook handling service which is 'wh-processor' gets the action ID from the webhook event and then stores it in the mysql database `user_events` table, based on the user. Then at the time we fetch the data, our data processing services will read those IDs from `user_events` and then will process the data. This workflow is working without an issue for now. But in the future, we will get more issues when the user count increases.

Then our data processing service will have to make more HTTP requests in a given period, which will increase the total processing time of the service, Rate limiting issues, resource issues, API timeouts, etc ... Not only that, keeping values in the SQL is also not a good option and can impact mainly on costing and performance as time passes.

To address those issues and improve the efficient workflow of data processing services even for large user counts we have to change the current workflow and storage services.

Decision

So for the improvement of Our whole data processing functionality, we going to,

  1. Replace the Cloud SQL with Google Cloud Datastore
  2. Update the Webhook handling service to fetch the API responses for receiving events upload them to Datastore (Google Cloud)
  3. Update the data processing service to read the API response from the Datastore and continue the rest of the workflow as before.

Replace the Cloud SQL with Google Cloud Datastore

Since we plan to store the API response, SQL is not a good option for those kinds of data ( Document type ). Google Cloud Datastore is the recommended service for storing document type details. Not only that compared to Cloud SQL, Datastore services are more manageable, can handle the load, and are cost-efficient which comparing with SQL on storing document type data.


Fetch the API response for webhook events from Webhook service `wh-processor`

Fetching the API response in real-time will help to reduce the API calls made from the data processing service in large numbers. This will directly affect to improve performance and reliability of our data processing service. Since the data processing service is responsible for processing data for the front end we have to make sure the service is working smoothly without too much work. Making API req from time to time will be a perfect solution for Ratelimit issues we getting time to time.

Note

When implementing the data fetching functionality on `wh-processor` will have to include a proper retry mechanism, also not only that somehow if the service (`wh-processor`) fails to fetch data for the webhook event, that event also needs to be stored in the Google Cloud datastore ( to protect consistency of customer's data ), Then at the time our data processing service trigger, it must need to fetch data for those API response missing webhook events.


Consequences

With these changes will get some Trade-off too on some services.

wh-processor service: Will have to couple with our Token Processing Services because we need to fetch the API response, therefore we need to get a Token for API Authorization. So any impact on the Token Processing service will affect this `wh-processor` service too.

wh-processor` service: Webhook Req processing time will get increase.

Token-Processor` service: Will get extra HTTP requests from time to time from the `wh-processor`, Therefor will require more resources & may be some improvement in code level.

DataStore and API Response service: Since we going to configure TTL for records, Will be not able to access the old fetched data if needed in the future.


Governance

Code Review: Done
UnitTesting: Done
Load Testing: Done


Notes

Original Author: user12@domain.com
Approval Date: 17th October 2024
Approved By: user17@domain.com
Superseded Date: --
Last Modified Date: --
Last Modified By: --
Last Modification: --

Mmmm… Seems there are a lot of texts, I hate to type. !!

Yeah there are, But you are only going to write an ADR when there is a change in Software Architecture only. ADRs not going to write on code level design changes ( inheritance, encapsulation etc .. ) and also for bug fixes which are not going to affect the architecture of the software.
Yeah it’s True that Softwares are constantly changing, But not its architecture.
Tip: You can reduce texts in the ADR by adding meaningful diagrams.


Where am I going to keep all those ADRs ??

You can keep your ADRs in the code repository. Create a Dir in the root of your project and manage your ARDs there.

What are the Advantages managing ADRs ??

1. Documentation of Decision Reasons:ADRs record will tell why the certain architectural decisions were made, including the context, options considered, and the reasoning behind it. These details will help future developers to understand the workflow without needing to rely on institutional knowledge or memory.

2. Consistency and Traceability: ADRs will provide a clear trail of decisions, ensuring changes in architecture over time. This helps teams maintain consistency of the system and to get reference decisions easily when needed.

3. Improved Communication: By providing a standardized way to discuss and document architectural decisions. All stakeholders, including developers, managers, and clients, can stay informed about decisions and their impacts.

4. Improve Change Management: When decisions are documented clearly, teams can better assess the impact of changes. If circumstances evolve, ADRs provide a foundation for deciding whether the current architecture still meets the needs or requires adaptation.

5. Support for Future Maintenance and Scalability: By understanding past architectural decisions will make it easier to maintain, refactor, or scale the system for future teams, Also teams will be able to be aware of any constraints or trade-offs that were previously considered.

6. Risk Management: ADRs help teams be mindful of technical debt and risk areas in the system. This is because from ADRs we can document the potential risks and how they were addressed in the decision-making process.

Knowledge Sharing and Onboarding: When onboarding new team members these ADRs will give insights into the system’s architecture and design choices. This will help to avoid the need for time-consuming, informal knowledge transfers.


[ Happy Coding ]

"CODIMITE" Would Like To Send You Notifications
Our notifications keep you updated with the latest articles and news. Would you like to receive these notifications and stay connected ?
Not Now
Yes Please