The team is the fundamental means of delivery at organizations. But organizations also need to ensure that the cognitive load on a team is not too high.
A team working with software systems that require too high of a cognitive load cannot effectively own or safely evolve the software. In this post, we will identify ways in which the cognitive load on teams can be detected and limited in order to safely promote fast flow of change.
First, let’s look at how to measure cognitive load.
Measure Cognitive Load
Ask the Question
A simple and quick way to assess cognitive load is to ask the team, in a non-judgmental way: “Do you feel like you’re effective and able to respond in a timely fashion to the work you are asked to do?”
While not an accurate measure, the answer will help gauge whether teams are feeling overloaded.
If the answer is clearly negative, organizations can apply some heuristics to understand if and why cognitive load is too high. If it is, the organization needs to take the necessary steps to reduce cognitive load, thus ensuring that the team is able to be effective and proactive again.
Incidentally, this will increase motivational levels within the team as members see more value and purpose in their work.
Beware Misguided Metrics
Trying to determine the cognitive load of software using simple measures such as lines of code, number of modules, classes, or methods is misguided.
Afterall, some programming languages are more verbose than others (and after the emergence of microservices, polyglot systems became increasingly more common), and teams using more abstractions and reusing code will have smaller but not necessarily simpler codebases.
Use Domain Complexity Instead
When measuring cognitive load, what we really care about is the domain complexity—how complex is the problem that we’re trying to solve with software?
A domain is a more largely applicable concept than software size. For example, running and evolving a toolchain to support continuous delivery typically requires a fair amount of tool integration and testing. Some automation code will be needed, but orders of magnitude less than the code needed for building a customer-facing application.
Domains help us think across the board and use common heuristics.
While there is no formula for cognitive load, we can assess the number and relative complexity (internal to the organization) of domains for which a given team is responsible.
Case Study: Domain Complexity at OutSystems
The Engineering Productivity team at OutSystems that we mentioned in this post realized that the different domains they were responsible for (build and continuous integration, continuous delivery, test automation, and infrastructure automation) had caused them to become overloaded.
The team was constantly faced with too much work and context switching prevailed, with tasks coming in from different product areas simultaneously.
There was a general sense in the team that they lacked sufficient domain knowledge, but they had no time to invest in acquiring it. In fact, most of their cognitive load was extraneous, leaving very little capacity for value-add intrinsic or germane cognitive load.
The team made a bold decision to split into microteams, each responsible for a single domain/product area: IDE productivity, platform-server productivity, and infrastructure automation.
The two productivity microteams were aligned (and colocated) with the respective product areas (IDE and platform server).
Changes that overlapped domains were infrequent; therefore, the previous single-team model was optimizing for the exceptions rather than the rule. With the new structure, the teams collaborated closely (even creating temporary microteams when necessary) on cross-domain issues that required a period of solution discovery but not as a permanent structure.
After only a few months, the results were above their best expectations.
- Motivation went up as each microteam could now focus on mastering a single domain (plus they didn’t have a lead anymore, empowering team decisions).
- The mission for each team was clear, with less context switching and frequent intra-team communication (thanks to a single shared purpose rather than a collection of purposes).
- Overall, the flow and quality of the work (in terms of fitness of the solutions for product teams) increased significantly.
Now that we can measure cognitive load, let’s look at a few effective ways to minimize cognitive load on teams
Team Cognitive Load Assessment
To help you on your journey, we’ve put together this simple assessment survey to help you determine the cognitive load of your team(s).
Restrict Team Responsibilities to Match Team Cognitive Load
One of the least acknowledged factors that increases friction in modern software delivery is the ever-increasing size and complexity of codebases that teams have to work with. This creates an unbounded cognitive load on teams. (Cognitive load also applies to teams that do less coding and more execution of tasks, like a traditional operations or infrastructure team.)
With a team-first approach, the team’s responsibilities are matched to the cognitive load that the team can handle.
The positive ripple effect of this can change how teams are designed and how they interact with each other across an organization.
For software-delivery teams, a team-first approach to cognitive load means limiting the size of the software system that a team is expected to work with; that is, organizations should not allow a software subsystem to grow beyond the cognitive load of the team responsible for the software.
If we stress a team by giving it responsibility for part of the system that is beyond its cognitive load capacity, it ceases to act like a high-performing unit and starts to behave like a loosely associated group of individuals, each trying to accomplish their individual tasks without the space to consider if those are in the team’s best interest.
Limiting the cognitive load for a team means limiting the size of the subsystem or area on which the team works.
At the same time, the team needs the space to continuously try to reduce the amount of intrinsic and extraneous load they currently have to deal with (via training, practice, automation, and any other useful techniques).
Limit the Number and Type of Domains per Team
To get started, identify distinct domains that each team has to deal with, and classify these domains into the following:
- simple (most of the work has a clear path of action)
- complicated (changes need to be analyzed and might require a few iterations on the solution to get it right)
- complex (solutions require a lot of experimentation and discovery).
You should fine tune the resulting classification by comparing pairs of domains across teams:
- How does domain A stack against domain B?
- Do they have similar complexity or is one clearly more complex than the other?
- Does the current domain classification reflect that?
Heuristics of Domains per Team
1) Assign Each Domain a Team
The first heuristic is to assign each domain to a single team. If a domain is too large for a team, instead of splitting responsibilities of a single domain to multiple teams, first split the domain into subdomains and then assign each new subdomain to a single team.
2) A Single Team Should Accommodate 2-3 Simple Domains
The second heuristic is that a single team (considering the golden seven-to-nine team size of Dunbar’s number) should be able to accommodate two to three “simple” domains.
Because such domains are quite procedural, the cost of context switching between domains is more bearable, as responses are more mechanical.
In this context, a simple domain for a team might be an older software system that has only minor, occasional, straightforward changes. However, there is a risk here of diminishing team members’ motivation due to the more routine nature of their work.
3) Teams Responsible for Complex Domain Should Have No Additional Domains
The third heuristic is that a team responsible for a complex domain should not have any more domains assigned to them—not even a simple one.
This is due to the cost of disrupting the flow of work (solving complex problems takes time and focus) and prioritization (there will be a tendency to resolve the simple, predictable problems as soon as they come in, causing further delays in the resolution of complex problems, which are often the most important for the business).
4) Avoid Single Team Responsible for Two Complicated Domains
The last heuristic is to avoid a single team responsible for two complicated domains. This might seem feasible with a larger team of eight or nine people, but in practice, the team will behave as two subteams (one for each domain), yet everyone will be expected to know about both domains, which increases cognitive load and cost of coordination.
Instead, it’s best to split the team into two separate teams of five people (by recruiting one or two more team members), so they can each be more focused and autonomous.
Match Software Boundary Size to Team Cognitive Load
To keep software delivery teams effective and able to own and evolve parts of the software systems, we need to take a team-first approach to the size of software subsystems and the placement of boundaries.
Instead of designing a system in the abstract, we need to design the system and its software boundaries to fit the available cognitive load within delivery teams.
Instead of choosing between a monolithic architecture or a microservices architecture, design the software to fit the maximum team cognitive load. Only then can we hope to achieve sustainable, safe, rapid software delivery.
This team-first approach to software boundaries leads to favoring certain styles of software architecture, such as small, decoupled services. We can visualize this team-first approach to software subsystem boundaries in the figure below.
On the left, we see typical software subsystem boundaries, with different parts of systems or products assigned to a mix of multiple teams, single teams, and individuals. On the right, we see the Team Topologies’ team-first approach to software subsystem boundaries, with every part of the system being team sized and owned by one team.
Reduce Intrinsic and Extraneous Cognitive Load to Increase Team’s Available Load
To increase the size of a software subsystem or domain for which a team is responsible, tune the ecosystem in which the team works in order to maximize the cognitive capacity of the team (by reducing the intrinsic and extraneous types of load):
- Provide a team-first working environment (physical or virtual).
- Minimize team distractions during the workweek by limiting meetings, reducing emails, assigning a dedicated team or person to support queries, and so forth.
- Change the management style by communicating goals and outcomes rather than obsessing over the “how.”
- Increase the quality of developer experience (DevEx) for other teams using your team’s code and APIs through good documentation, consistency, good UX, and other DevEx practices.
- Use a platform that is explicitly designed to reduce cognitive load for teams building software on top of it.
By actively reducing extraneous mental overheads for teams and team members through these and similar approaches, organizations can give teams more cognitive space to take on more challenging parts of the software systems.
Conversely, if an organization does not have team-first office space, good management practices, and especially a team-first platform, then the size of software subsystems that teams can take on will be smaller.
A larger number of smaller parts requires more teams to work on them, costing more. Taking a team-first approach to software subsystem boundaries by designing for cognitive load means happier teams and (eventually) lower costs.
Limit Teams’ Cognitive Load and Facilitate Team Interactions to Go Faster
In a fast-changing and challenging context, teams are more effective than groups of individuals. Successful organizations—from the US military to corporations large and small—treat the team as the fundamental means of getting work done.
Teams are generally small, stable, and long lived, allowing team members the time and space to develop their working patterns and team dynamics.
Importantly, due to limits on team size (Dunbar’s number), there is an effective upper limit on the cognitive load that a single team can bear. This strongly suggests a limit on the size of the software systems and complexity of domains that any team should work with.
The team needs to own the system or subsystems they are responsible for. Teams working on multiple codebases lack ownership and, especially, the mental space to understand and keep the corresponding systems healthy.
The team-first approach provides opportunities for many kinds of people to thrive in an organization. Instead of needing a thick skin or resilience in order to survive in an organization that atomizes individuals, people in a team-first organization have the space and support to develop their skills and practices within the context of a team.
Crucially, because communication between individuals is de-emphasized in favor of communication between teams for day-to-day work, the organization supports a wide range of communication preferences, from those people who communicate best one to one to those who like large group conversations. Furthermore, the effect of previously destructive individuals is curtailed. This humanistic approach is a huge benefit of choosing teams first.
This post was adapted from the book Team Topologies: Organizing Business and Technology Teams for Fast Flow by Matthew Skelton and Manuel Pais.