In this post, I want to discuss how to design and organize product teams. When I say product teams, I don't mean product management teams, but rather, a team who builds products. To build a product, you need various skills such as engineering, design, product management, support.
Products typically start with a small team or even only one engineer. It depends, but you usually need to think about team design when you reach at least ten people working on the product. After you reach that number, you need to divide work between teams. You might also want multiple teams to work in parallel. But how to do that? Well, there are a lot of ways.
You might have a system or an app. That system consists of multiple components, and you have numerous features on the pipeline. To better explain the situation, let's say you have three teams, three components in your system, and three features you want to develop. Your team has grown in numbers, and it's a waste of time to have three teams to work on feature A until done, then do feature B, and then C. Bear in mind, you typically want the teams to work in parallel.
To do this, you assign a feature to each team. That sound reasonable enough. In the diagram below, F stands for a Feature, and C stands for a Component.
It sounds nice that each team works independently on a complete and separate feature, and they work in parallel. Now, we can deliver features faster, right? Or so, I thought.
The big downside of this approach is that to take a feature and implement it from A to Z, you need to touch multiple components, and here in our small system with only three components, you need to touch all three of them! That's a lot of stepping on other people's work and potential areas of conflict. You need a lot of coordination between the teams to make this happen so you really get back to one big team.
Another downside is that the teams have no ownership over these components. Everyone's goal will be to deliver the feature they are assigned to, even if that means doing changes in one component that will negatively impact other teams' features.
In short, there will be chaos over the artifacts produced by the team, be that the code, design, documents, and so on, because different teams will change these artifacts based on different purposes.
Ok, how about we divide the team by components instead of features?
Now, each team has complete ownership over its components. It also sounds reasonable because each change in a component is typically well-thought-of and will not (hopefully) break other changes related to other features.
But, of course, there will be downsides. The biggest one is that now to implement a feature, you need to talk to three teams, you need to decompose the feature into three sub-features for each team, and each team needs to understand the full feature to tackle the sub-feature.
So, there will be a lot of back and forth between the teams to develop these features, drastically slowing down the work. Again, you really get back to one big team
In short, there will be chaos in communications between the teams.
There is a third bad way to organize product teams, and really the worst. Yet, I saw teams work this way in my career.
In this way, no team is assigned to a particular component or a particular feature, they work in constant iterations (or so-called sprints), and at each iteration, they rotate teams or rotate members within the teams. The rotation is typically based on availability, or managers throw "jokers" around, thinking they will speed up the highest priority tasks.
Another rationale I sometimes hear working this way is that when rotating people, they will be masters of everything inside the system. But most likely, they will be masters of none.
Typically, the purpose of such an organization is to be a features factory, manufacturing features without any real value or purpose. Only delivering one feature after another and leaving behind a wake of destruction.
This is absolute mayhem; please don't use this form of organization (or lack of).
The best way to organize product teams is by domain.
The term domain has many definitions. The simplest is that the domain is an area of interest to the business.
Here is a more advanced definition by Eric Evans:
A sphere of knowledge, influence, or activity. The subject area to which the user applies a program is the domain of the software.
Domain-Driven Design is a well-known software design technique that uses a common language between system builders and business domain experts.
It's not easy to identify domains, unlike features and components. But it's critical to identify them in order to design truly independent, empowered, and expert products teams.
So, for our purpose in designing or organizing product teams, let's define a domain as a group of related components.
Features, in most cases, require changes in multiple components, but they typically map one-to-one to domains.
So, if you have a domain team, the team will be responsible for the same related components in that domain. They will have complete ownership over these components.
The domain team will also be able to do features from A to Z that are related to that domain. So, you really take the best of both the component team and the feature team we discussed above.
If a feature needs changes in two domains, think twice about the feature or the boundary between domains. Most likely, the feature is actually a multiple of features, not one. Or if it's really one feature, then the domains are probably not designed well.
The difficulty with designing domain teams is to actually identify the domains. There is no simple solution, but i will give a simple example and more resources to checkout at the end of the article.
Domain Teams Example
Let’s say you have a car renting application. Users will use your app to discover cars. If they like one, they can reserve it and then pay and collect it.
Notice in this simple sentence, we can identify three areas of interest to the business:
- Discoverability: users should have a way to discover available cars based on distance, preference, etc..
- Reservation: users should be able to reserve a car once they find a suitable one.
- Payment: users should be able to pay through the application.
So, we identified three domains. Now we can organize our teams based on these domains:
- Discovery Team
- Reservation Team
- Payment Team
As we discussed above, features typically map one-to-one with domains.
For example, let’s say we want to implement a new feature. We want users to filter cars based on a luxury level. Well, that’s a discoverability concern for sure, so we assign this feature to the discovery team.
Let’s also say we don’t want users only to reserve one car; maybe some customers need several cars at once. That’s a reservation concern; we can assign this feature to the reservation team.
As the last example, maybe we want users to be able to split their payment or have payment plans. That’s a payment concern, so we assign this feature to the payment team.
Please note these are trivial examples. I just wanted to give you an idea about domain teams before ending this article. If you think hard enough, you might come up with a feature that requires changes in two or three of the domains we identified above. That’s why there are more involved techniques for identifying domains in your business, such as domain event storming, domain message flow modeling, bounded context, and context mapping.
Team’s Cognitive Load
Each domain can be pretty complex. Imagine the scenarios and edge cases that need to be handled by the reservation team, such as:
- Cars availability, such as cars already rented, cars that need maintenance, or cars that are being transported from one branch to another.
- Renter eligibility based on law or history.
- Notification and status update about a reservation, such as reserved, ready to pick up, in progress, or declined.
I’m sure there are a lot more.
The reservation domain team can and should be masters of reservation and all its intricacies. But they cannot nor should be masters of discovery and all its intricacies and payment and all its intricacies.
When designing teams, we should thoughtfully think about the cognitive load required for each team.
The domain teams are really powerful. With domain teams, you will have the following:
- Independent teams with minimum coordination between them.
- Complete ownership over their work, from planning, requirements gathering, and design to development, testing, and deploying to production.
- They can't be experts in all of your business and its systems, but they are masters of their domains.
- Manageable cognitive load for each team
- Expect things to move really fast without sacrificing quality.
- Expect novel solutions to business problems.
Thanks for reading.