Dark energy force: team autonomy
microservice architecture architecting dark energy and dark mattera dark energy, dark matter force
Team autonomy is the ability of a team to make decisions and take actions without the need for approval from other teams. Let’s first look at why team autonomy is important for rapid, frequent, and reliable software delivery. Then we’ll look at how to achieve it.
Why is team autonomy important?
The authors of the book Accelerate found that it is an essential aspect of high performance software delivery. A team should be able to develop, test and deploy their software (i.e. subdomains) independently of other teams.
That’s because coordinating with other teams is a source of delays and bottlenecks. You need to schedule a meeting, determine what needs to be done, and then wait for the other team to do the work. In many organizations, meeting rooms are in short supply. Moreover, research has found that decision making within teams (e.g. at the daily standup), is much faster than decision making across teams.
The challenge with developing a large application is if there are N
teams, then according to The Mythical Man-Month each team potentially has to coordinate with N-1
teams.
The coordination effort is proportional to O(N^2)
- the edges in an undirected graph with N
vertices.
As a result, the coordination effort grows very quickly as the number of teams grows.
It’s essential that we design an architecture that minimizes the coordination effort between teams.
Designing for team autonomy
There are three different design techniques that improve team autonomy:
- Design loosely coupled subdomains
- Use a modular monolith to separate subdomains
- Use a microservice architecture to physically separate subdomains
Design loosely coupled subdomains
Team autonomy requires that subdomain that are owned by different teams are loosely coupled from a design-time perspective. Loose design-time coupling minimizes how often teams need to coordinate with each other. It’s usually achieved by designing stable APIs that encapsulate the subdomain’s implementation details. It’s also beneficial to minimize each subdomain’s inbound and outbound dependencies, since each one is a potential reason for change and, hence, collaboration. Once you have designed your subdomains to be loosely coupled, you can then use a modular monolith or a microservice architecture to physically separate them.
Use a modular monolith
In a monolith, this can be accomplished to some degree by having a modular monolith, which organized around the subdomains rather than technically oriented layers. Instead of every team working on every layer, each team owns and develops their subdomain module. They mostly need to coordinate from time to time with the teams that own their subdomain’s inbound and outbound dependencies.
One limitation, however, of a modular monolith is that all teams are contributing to the same code base.
Multiple teams will need to coordinate some kinds of changes, such as upgrades of dependencies, such as frameworks and libraries.
For example, let’s imagine that the Order Management
team wants to use a library that depends on a newer major version some library that’s already being used by numerous other subdomains.
They will need to spend time coordinating the upgrade with the teams that own each of those subdomains.
As a result, the coordination effort is still proportional to O(N^2)
.
Use the microservice architecture
When developing a large application, an even better way to physically separate the subdomains is to use the microservice architecture.
Each team owns a service, which they can develop, test and deploy independently of other teams.
They only need to periodically coordinate with the teams that own their services’s inbound and outbound dependencies.
Moreover, the team is free to make many technology choices independently of other teams.
For example, unlike when developing a modular monolith, if the Order Management
team owns their own service they can use any library they want without having to coordinate with other teams.
The primary source of application-wide changes is the application’s infrastructure, such as the message broker and deployment platform. Any changes to the infrastructure will likely require coordination with all teams. Fortunately, such changes are relatively rare and are presumably only made for good reasons.