ADRs as a Tool to Build Empowered Teams

Learn how we use Architecture Decision Records (ADRs) to build empowered, autonomous teams, enhancing decision-making and collaboration.

In a couple of our projects the teams introduced Architecture Decision Records (https://github.com/joelparkerhenderson/architecture_decision_record) a while ago. In this blog post I want to summarize what team rules were defined for writing, reviewing and storing ADRs and will discuss the implications of these rules and why I believe that these rules work as a tool to build empowered teams.

What’s an Architecture Decision Record (ADR)?

An ADR in short is a well documented architecture decision process. An ADR does not require any special template or place to store it. I recommended that each ADR contains at least an ID (for example 0001-use-vuex-as-state-store), title, date, status, context, decision and consequences.

The ID allows to reference the ADR for example in a commit message. The title acts as a short summary of the decision, the status documents the state of the decision, context describes why there was a need for a decision, the decision part describes the outcome and consequences what to expect from the decision.

I prefer to store ADRs “near the architecture”. I prefer storing ADRs in Git as Git gives you a history for free, to further explore the history of the decision making process.

I try to keep the template as simple as possible to make it easy for every team member to learn how to write an ADRs. As a consequence I used only 3 status: “pending” (in discussion, not yet approved), “approved” (the whole team commits to that decision), “obsolete” (the decision was declined or is just not relevant anymore or superseded by another decision). In the team I’m currently working we’re evaluating if a fourth status “declined” will help in understanding the architecture decision history or just make things more complicated.

ADR Team Rules

Some of these ADR rules were decided on by the team, some of these rules were never stated but implicitly agreed by the teams by following the rules. The team did created three simple rules:

Every team member can file an ADR

  • Every team member has the opportunity to actively shape the architecture.

  • Architecture decisions can be done more quickly.

  • The team itself defines what architecture is and what not.

  • There is no ivory tower architect involved.

  • A decision taking mechanism has be be setup to guide architecture decisions.

  • Decision making process can be fully asynchronous which is a good idea in distributed teams.

An ADR has to be reviewed by every team member

  • Everyone in the team is informed of architecture decisions.

  • Makes onboarding team members easier because they can understand what decisions where taken, when and why.

  • Decreases the bus factor in certain areas of the software because (architecture) information is the first step to understand the code.

  • Reduces information gap between backend and frontend teams. It’s one architecture and every team member should have the full information about the architecture.

  • Reduces team splits and silos, for example in backend and frontend teams.

Store ADRs in Git

  • ADRs are bound to the architecture.

  • Not just the decision but the whole decision process is versioned (ADR was filed, accepted, made obsolete) and can be viewed by just “git log”.

  • PRs for proposing ADRs can be used for discussions if the team is using Github, Bitbucket or the like.

Team Impact

In some project setups, that have a (non coding) software architect role I made the observation that these teams fall short when it comes to engagement, commitment or delivering value.

I believe that this shortcoming is introduced by the lack of autonomy of the team members to decide on the software architecture.

Let’s take a look at a definition of empowered teams and how key attributes of this definition are related to the ADR rules.

Empowered teams are self-sufficient groups of people working together with specific goals. They have the corporate authority, experience, responsibility and skills to enact their own decisions for the organization.

https://www.qualitydigest.com/mar99/html/body_teams.html

For me, the key attributes in this definition are “authority”, “experience”, “responsibility” and “skill” to take decisions. While the definition above focuses on a broader corporate scope, I focus on a more narrow software architecture scope.

I believe that “Every team member can file an ADR” is an opportunity to grant authority (on the architecture level but not on a corporate level) to the team and learn to architect a solution and thus leverage experience. I learned that an agreed decision process has to be established by the team to deliver the quality “architecture decisions can be done more quickly” and to prevent important architecture decisions to be stale and undecided for a long time.

While I wanted to enforce that “there is no ivory tower architect involved”, I see a strong need for a decision maker role that is empowered by the team to take decisions if no consensus or compromise can be established.

As a counterpart to “Every team member can file an ADR” the rule “An ADR has to be reviewed by every team member” gives every team member a (limited) responsibility for decisions and increases architecture skill.

Team members learn from other team members how to get an architecture decision started and how architecture is done. What does architecture solve? Are there always architectural downsides when taking a decision?

I learned that “reducing the team split” is not as simple as “ADRs will reduce the team split by magic”. Ensure that every team understands the implications of an architectural decision. It should be a daily habit to make sure that team members do not start accepting ADRs because of a “this is not their area” attitude. This behavior is a clear sign that team members do not feel responsible for the software as a whole to work correctly but feel only responsible for their limited area of work.

Summary

If you’re in an architecture role I strongly recommend to take a look at ADRs as an alternative to writing (big upfront) architectural documentation. I recommend you use (or at least start with) a simple ADR template as proposed by Michael Nygard ( http://thinkrelevance.com/blog/2011/11/15/documenting-architecture-decisions). Ensure that teams make and record architecture decisions and that those decisions are read, discussed and understood by the team rather than just blindly accepted. With a working architecture decision process based on ADRs you can drive team qualities as authority, experience, responsibility and skill in an architecture context.

Blog 7/14/21

Building and Publishing Design Systems | Part 2

Learn how to build and publish design systems effectively. Discover best practices for creating reusable components and enhancing UI consistency.

Blog 10/21/20

Consistency and Aggregates in Event Sourcing

Learn how we ensures data consistency in event sourcing with effective use of aggregates, enhancing system reliability and performance.

Blog 5/18/22

Introduction to Functional Programming in F#

Dive into functional programming with F# in our introductory series. Learn how to solve real business problems using F#'s functional programming features. This first part covers setting up your environment, basic F# syntax, and implementing a simple use case. Perfect for developers looking to enhance their skills in functional programming.

Blog 1/29/20

Tracing IO in .NET Core

Learn how we leverage OpenTelemetry for efficient tracing of IO operations in .NET Core applications, enhancing performance and monitoring.

Blog 8/10/22

So, I wrote a book

Join me as I share the story of writing a book on F#. Discover the challenges, insights, and triumphs along the way.

Blog 11/30/22

Introduction to Partial Function Application in F#

Partial Function Application is one of the core functional programming concepts that everyone should understand as it is widely used in most F# codebases.In this post I will introduce you to the grace and power of partial application. We will start with tupled arguments that most devs will recognise and then move onto curried arguments that allow us to use partial application.

Blog 3/22/23

Introduction to Functional Programming in F# – Part 8

Discover Units of Measure and Type Providers in F#. Enhance data management and type safety in your applications with these powerful tools.

Blog 7/12/23

Introduction to Functional Programming in F# – Part 11

Learn type inference and generic functions in F#. Boost efficiency and flexibility in your code with these essential programming concepts.

Blog 3/22/23

Introduction to Functional Programming in F# – Part 9

Explore Active Patterns and Computation Expressions in F#. Enhance code clarity and functionality with these advanced techniques.

Blog 5/17/23

Introduction to Functional Programming in F# – Part 10

Discover Agents and Mailboxes in F#. Build responsive applications using these powerful concurrency tools in functional programming.

Blog 8/8/23

Introduction to Functional Programming in F# – Part 12

Explore reflection and meta-programming in F#. Learn how to dynamically manipulate code and enhance flexibility with advanced techniques.

Blog 12/22/22

Introduction to Functional Programming in F# – Part 7

Explore LINQ and query expressions in F#. Simplify data manipulation and enhance your functional programming skills with this guide.

Blog 12/22/22

Introduction to Functional Programming in F# – Part 6

Learn error handling in F# with option types. Improve code reliability using F#'s powerful error-handling techniques.

Blog 9/15/22

Introduction to Functional Programming in F# – Part 3

Dive into F# data structures and pattern matching. Simplify code and enhance functionality with these powerful features.

Blog 9/13/22

Introduction to Functional Programming in F# – Part 2

Explore functions, types, and modules in F#. Enhance your skills with practical examples and insights in this detailed guide.

Blog 10/1/22

Introduction to Functional Programming in F# – Part 4

Unlock F# collections and pipelines. Manage data efficiently and streamline your functional programming workflow with these powerful tools.

Blog 10/11/22

Introduction to Functional Programming in F# – Part 5

Master F# asynchronous workflows and parallelism. Enhance application performance with advanced functional programming techniques.

Blog 7/15/21

Building a micro frontend consuming a design system | Part 3

In this blopgpost, you will learn how to create a react application that consumes a design system.

Blog 11/3/22

Inbox helps to clear the mind

I hate distractions. They can easily ruin my day when I'm in the middle of working on a cool project. They do that by overloading my mind, buzzing around inside me, and just making me tired. Even though we can think about several things at once, we can only do one thing at a time.

Blog 6/24/21

Using a Skill/Will matrix for personal career development

Discover how a Skill/Will Matrix helps employees identify strengths and areas for growth, boosting personal and professional development.