Functional Teams or Feature Teams?

As Zoosk Engineering has grown throughout the years, we’ve aligned our teams in different ways based on the needs and challenges that our organization was facing at that time. One of our core values is to continually challenge the status quo by always looking for ways do our work better and faster by encouraging calculated risks in order to achieve our goals. That said, last year, we made a fundamental change in how we implemented feature development at Zoosk by moving our main feature development teams away from organizing around function to organizing around features. In this article, I’ll go over what this meant for Zoosk, the lessons learned, and the areas of continued focus from working in this style over the past year.

What did the teams look like before?

As with most startups, we started with a very flat engineering organization with a handful of people. As the team grew rapidly, we began to specialize and form teams in different functional areas based on the main technology platforms that we supported. This is a fairly common way to organize, and at Zoosk it looked something like this:

Screenshot 6:3:16, 10:39 AM

What were the problem areas?

This worked very well for us during our high growth phase, but there were a number of pain points that became evident as we continued to scale our engineering and product management teams.

Speed of Development

Given that most features at Zoosk require parity on all client platforms, to complete a feature across all of them, it must be scheduled through each of the respective teams from the diagram above. This would require one product manager to work with potentially seven different leads or representative PMs in order to complete a project. Just by the sheer number of touch points, it created opportunities for things to slip through the cracks and a lot of communication overhead. Also, if a project requires multiple iterations (which 99% of them do), this cost gets very high very quickly.

Skin in the Game

At Zoosk, we move very quickly, which in itself isn’t a bad thing by any means. One of the side effects of that, mainly for the teams on the backend, was that some of the teams would already be onto their next project before the previous project had fully rolled out. For example, because we used to require that API endpoints be completed before the client work had even started, it was very likely that the developers on the API team would be onto the next feature, and the previous project was out of sight, out of mind. This system definitely worked, but it made it a little harder to really appreciate and learn from a project holistically when you were already onto the next thing, and it could start to feel more like a factory.

Opportunities for cross-training

With a functionally organized team, it naturally lends to itself to supporting career development towards being an expert in that functional area. While we do expect our engineers to specialize in a particular function to a certain extent, it’s harder to support generalists that want to get exposure in different areas of the stack. In the past, this would require an engineer switching to a different team, which is a big commitment for the individual and the company. We always support this type of career development, but because of the commitment level, it might not work for everyone. For example, if your passion is iOS development, but you are still interested in spending some time on the backend just to get more context there, moving to the API team full-time might not be where you want to focus your career.

What do the teams look like now?

After identifying the inefficiencies we wanted to try to improve on, and reading a lot about how other companies have organized, this is what we came up with (with the new teams highlighted in green):

Screenshot 6:3:16, 10:38 AM

Web Feature Teams

The main idea is that these feature teams will own features across both our desktop web and our mobile web platforms. These teams were initially combined with developers from UI, Javascript, API, and Microservices teams, and each have a dedicated PM. One of the advantages of web development as compared to native development is the pace at which you can iterate. Without being limited by the iOS store or waiting for application code uptake on all native devices, you can move much quicker. For Zoosk, it makes much more sense to iterate and optimize through A/B testing quickly on the web, then afterwards, move over to the native clients to complete feature parity on iOS and Android. That said, the Web Feature Teams end up doing most of the heavy lifting for the backend API and Microservices work, and by the time it reaches the native clients, there are rarely any changes needed on the API side.

Functional Native Teams

We initially thought about bringing native developers into the feature teams as well, but we decided not to for a couple of reasons. Firstly, we felt that for the teams to have enough redundancy, we needed at least two developers for each technology stack. The jump from Javascript / UI Developer (HTML/CSS and Javascript) and API / Microservices (mainly PHP and some Java) seemed to be less costly than going from Android to iOS since you’re talking about the cost of likely learning a new language in the latter. Secondly, we thought this would be easier to add later on while we’re working on getting the processes right for the new organization.

Architecture and Infrastructure Team

This team is responsible for overseeing the processes around ownership and direction of the different platforms. This does not mean they dictate the direction of these platforms but rather facilitate how they move forward by prioritizing our engineering driven initiatives. For example, the Architecture team drives our Web Developer meetups where  developers from all teams meet to talk about the different problem areas in the codebase, opportunities for improvement, and how we want to prioritize those.

What’s working?

At this point, we’ve been functioning in this system for about a year, and these are some of the takeaways from moving to a feature team organization.

Speed of Development

With the new structure, we reduced the number of communication touch points from seven, down to three at the most. Also, by focusing on optimizing on the web before native clients, we’re able to optimize and decide on the main direction of the feature on web without spending as much time optimizing on native clients. There are obviously things that don’t translate from mobile web to native, but if we can figure out 80% of that, it’s still a win.

Skin in the Game

With the advent of Lotus and our improved development pipeline, client developers are able to work in parallel with backend developers for most of our feature work. This, along with a dedicated PM for each feature team, enable us to work very efficiently.  It allows for developers on both sides of the stack, as well as their dedicated PM, to really own the feature holistically which wasn’t the case for everyone before.

Opportunities for cross-training

For the team members on the web feature teams, cross-training was a necessity to ensure redundancy within the teams. Initially, UI developers and Javascript developers cross-trained with each other and Microservices developers cross-trained with API developers. Because of that, we now have great systems in place to allow any developer from any team to quickly get up and running on any of our different codebases.  Really, anyone (even non-engineers) can check into any codebase as long as they follow the guidelines we have set up. For example, we occasionally have tweaks to make in the API layer when features make their way to the iOS or Android teams. With our new processes around code reviewing and feedback, our native developers were able to get up to speed quickly and to make small changes using the existing mechanisms that we set up for the feature teams.

What needs improvement?

Feature First on Native

We knew this was a tradeoff we were making when we initially moved to this system, but it became very evident when we tried to build a feature first on one of the native clients. Because the feature teams are optimized to work on the backend and client work in unison, there were a number of things that fell through the cracks as we completed the API first in a feature team, then moved onto the client work in the native teams.  That said, one of the changes we do plan on making is adding dedicated backend resources to the native teams to allow them to take on more backend heavy work.

Platform Improvements and Tech Debt

In a functional world where each team owns a platform, it’s very clear which team is in charge of constantly improving their respective platforms, tracking tech debt, and triage queues. In this new system (for us), it took awhile to get the processes just right around how the Architecture and Infrastructure team would manage the platform improvements. We still expect and encourage the developers on each feature team to participate and contribute to technical improvements on their functional platforms of expertise, but we went through a few iterations on the best way to do that.

Triaging

Because of the large feature set we’ve accrued over the years, it wasn’t exactly easy or obvious how to split up those different sets between the feature teams in an intuitive way. There were a number of times when tickets would be filed to the wrong team, or we spent too much time trying to figure out exactly where the ticket should go. In a functional world, it’s a lot clearer. If there’s a bug on mobile web, it goes to the mobile web team. Correspondingly, a bug on desktop web goes to that team.

So which way is right?

Each organizational structure has it’s pros and cons, so it really depends on the situation. It’s always hard to tell what would have happened had we not switched, but overall these changes made sense for Zoosk Engineering at the time and hopefully these main takeaways will help you as you think about your organization.