Independent self-organizing teams are the key to scaling your Engineering department. Each team must be able to ship features without depending on others. To get to that point, we must work hard to avoid team dependencies.
The stereotypical example of a team-level dependency is the combination of a front-end and a backend team. The former can't get started without the latter. The latter can't deliver a feature without the former. It’s a structural dependency and we all know to avoid this like the plague. But sometimes, these dependencies are less obvious to break.
Sometimes, occasional dependencies at the team level need to be addressed. In those cases, it makes sense to synchronize teams.
Rather than having each team work on separate Focus blocks, you assign the same issue to both teams. There are simple syncs and more elaborate ones.
Here are the three common scenarios where syncing teams makes sense.
Collaboration
Let's start with the most obvious one. Sometimes, you want both teams to work on the same problem simultaneously. Let's say we're overhauling the branding and style of our product. Since this has to happen in both web and mobile apps, it makes sense to sync those teams.
We don't want to find out that iOS doesn't play nicely with our new button styles after the web team has already done its part! Instead, we want both teams to work on the same problem and share learnings. Maybe they can even use this opportunity to create shared reusable components.
We plan this by assigning the same Focus block to both teams. For the duration of this block, they act as one team.
Support combo
Another common scenario is when both teams can work independently, but knowledge isn't evenly distributed. Let's say the web team builds a report on mobile usage. While they have all the tools to build the report, they might not know how to get the most out of mobile session data. They might want to lean on the specialists for that. Maybe they even want to add extra metrics to the mobile app.
This creates a situation where we know that the mobile team might be affected but can't have them focus on the problem. There is no problem for them to solve—they are there to support the web team.
In that case, we also sync Focus blocks for both teams. In addition, we assign a Recovery block for the mobile team. They are available to support the web team, but if they can’t help, they'll work on operational tickets.
This support combo is also a great way of sharing knowledge in those early days when independent teams are still finding their independence and knowledge isn’t evenly disctibuted yet.
Classic scope dependency
Sometimes, the classic scope dependency can't be avoided. Sometimes, having one team build Task A before the other team starts Task B makes sense.
Let's say we want the users to upload a video through mobile, which can be viewed on the web app. In theory, recording and playback are two separate features. Both teams could work independently. In practice, however, it makes no sense to begin developing the playback feature before recording. It's pretty easy to see how the web team could make bad assumptions about video formats and data structures that would hinder the mobile team. That would most certainly end up in rework.
We want to tackle the most technically challenging part first, and that creates a dependency.
The way we sync these teams is a bit more complicated. First, the mobile team gets a Focus block to build the recording functionality. After that, the web team builds the playback feature. The crucial part is where we place the Recovery blocks. While the web team does their magic, mobile is there to provide support if needed. After both are done, there is yet another Recovery block to make sure any loose ends can be tied up.
Syncing teams is a powerful way of sharing knowledge when used sparingly. Dependencies can be pretty costly and should be an exceptional situation. If they become the norm, there is something wrong with the overall team design.