Autonomy and collaboration are two buzzwords in engineering management, and rightly so; they are both critical in developing and scaling a high-performing product team. As your organisation grows, more collaboration is required and teams feel their autonomy slipping away from them. Contracts is a simple concept which can help ease the tension, giving teams autonomy while maintaining a coherent strategy.

Autonomy

In its purest form, autonomy means ‘doing whatever you want’. When teams ask to be more autonomous, they usually mean that they don’t want to be told what to do by someone else. We can frame this more positively; an autonomous team is a team that is empowered to make decisions on its own, and for those decisions to drive their day-to-day activities.

Numerous studies have shown that autonomous teams lead to higher employee satisfaction. That’s also been my anecdotal experience: lots of engineers react negatively when a decision is taken ‘over their heads’, or they don’t feel in control of their own destiny. This leads to higher productivity and better employee retention.

Giving teams autonomy helps you make the most of everyone in the team: if all the important decisions are made at the top of your organisation, why did you hire all those smart people? Additionally, often the people closest to the problem will make the best decisions, not those with the most senior title.

Giving teams autonomy also reduces bottlenecks. If decisions can be taken within the team they don’t get blocked waiting for someone else to prioritise their issue. It also frees up your leaders to focus on more valuable strategic work.

Autonomy is often linked with chaotic environments, and you can see why. If every team decides what to do in isolation, then it makes effective collaboration challenging. How do you set a strategic vision? What happens when teams inevitably need to share processes or tools? How can you manage inter-team dependencies?

Making Autonomy Work: Collaboration

It’s not realistic to imagine an organisation where every team makes its own decisions completely independently from everyone else. In order for an organisation to be more than the sum of its parts, the teams need to meaningfully collaborate.

That collaboration takes many forms including:

  • delivering large features that are too big for a single team to complete
  • delivering complementary features in technically unconnected product areas to pursue a strategic vision
  • sharing knowledge and expertise - prevent ‘re-inventing the wheel’

As a company scales, teams with names like ‘platform’ and ‘enablement’ emerge whose raison d’être is to support other teams in achieving their objectives. Collaboration becomes something that needs to be prioritised as the 5 engineers sat in a basement becomes 20, then 50, then 100.

Unfortunately, as teams need to collaborate more, they often feel less autonomous. Rather than prioritising their own work, there are company priorities and objectives they need to contribute to, or perhaps other teams who they need to support. Communication becomes more difficult, and it becomes harder to get ‘buy-in’ from team members to pursue certain types of work.

If teams believe that they should be autonomous, this collaboration can cause anxiety and stress as teams are not able to act independently. If we’re not careful, the collaboration undermines all the benefits we discussed above: employee satisfaction decreases because team members feel that they aren’t being listened to or allowed to solve the problems that they think are important, decisions end up being taken higher up the organisation to ‘grease the wheels’ and get teams collaborating faster, and bottlenecks appear as work becomes more interdependent and teams specialise.

Using Contracts

It’s an overused analogy, but imagine your organisation is a software product split into services (teams). When we architect software into multiple services, we prioritise autonomy to help build high performing, resilient systems. For this to work, we define contracts that each service needs to fulfill. We can then give the service autonomy about how it delivers those contracts, because the other services are only relying on the behaviour specified in the contract. These contracts aren’t just interface specification documents. They also involve non-functional requirements such as speed and availability, as well as logical requirements such as immutability or consistency.

Of course, this is a lot easier with computers than humans, but the principal remains the same. To give teams maximum autonomy, you want to define contracts which other teams can rely on so that the day-to-day implementation decisions can be safely taken within the team.

🔎 Clarity

Contracts are only effective when everyone has the same understanding of the contract. That means you need communication - either in person or via documentation - to drive alignment. Teams can be autonomous but still contribute to a strategy if the expectations are clear and well understood.

Clarity should be both about what is being worked on, and also when. This doesn’t mean teams have to commit to deadlines - we all know the perils of that approach - but it does mean teams need to be clear about what timeline expectations should be, and then continue to manage those expectations. For example, the importance of the distinction between ‘we will deliver this by 1 Oct’ and ‘we aim to deliver this by 1 Oct’ cannot be overstated.

Sometimes you might also need clarity regarding the how, for example if two teams are working on projects that impact the same shared code. However, this should be avoided wherever possible, as it muddies the waters and hurts the autonomy of the team for limited benefit. If you get to this situation, it’s worth taking a second to question whether or not the teams are divided correctly. Alternatively, can you change the how into a contract requirement - such as ‘it will provide a reusable system to support data replication’ rather than a full implementation description.

🕰️ Longevity

For teams to be effective, the contracts they are working to fulfill need to be long-lived. Continuing priority changes cause re-work and discarded work, which immediately reduces a team’s effectiveness while also hurting morale. A big part of autonomy is planning; feeling like you as a team have control over what the next [n] weeks of work look like, and getting excited and emotionally invested in what’s to come. If that plan keeps shifting, team members become disillusioned and pessimistic. This is because the shifting in priorities is taking away the team’s autonomy.

👓 Transparency

The final piece of the puzzle is transparency, which is largely about how the contracts are decided in the first place. To implement a coherent vision there are often key decision makers at the top of an organisation, who realistically cannot consult with every team member. However, there’s no reason not to communicate clearly about how the prioritisation process takes place and what factors are considered. This is also a classic strategy for getting buy-in from teams: if teams understand why the decision was made it’s easier to get behind it.

Implementation

The first step here is to establish a framework where these contracts are agreed. OKRs or any other kind of objective structure are a good starting point. Making these explicit can help identify other issues, such as teams without a clear direction. It’s important to make these objectives / contracts as high level as possible; at every step challenge yourself to abstract it one more level up. As an example, the contract should ideally not say ‘build API [x]’ but instead ‘improve outcome [y]’. Inter-team contracts might look a bit different, particularly for enablement / platform teams, but the principals remain the same. For autonomous teams to collaborate effectively you need clear contracts between teams, which are long-lived and derive from a transparent process.