Almost exactly two years ago, we shared how engineers work at Smartly.io in this blog post. Since then, our product organization has doubled in size, and we have gone from six development teams to 13. Here’s how our ways of working have changed—and stayed the same.
We have to constantly adapt our ways of working and find new and better ways to operate in the fast-changing environment. It’s a process of creative destruction: old ways become obsolete, and new approaches are born out of new needs. In refreshing our engineering team’s working agreements, our mission has been to find the minimum level of coherence where we can function while allowing maximal autonomy to development teams.
Our engineering team consists of 13 full-stack development teams, each of which owns a particular product area. They enjoy a high level of independence that hasn’t changed over the years. The teams own their roadmap and are in charge of improving the technical solutions as well as managing the technical debt of their product area. They are equipped with frontend, backend, DevOps, product design, and product management skills which empowers them to develop their product area end-to-end.
We have chosen to build full-stack teams instead of separating each of the different skill sets to their own groups, because it empowers self-organized ways of working. The development teams are autonomous units with their own products and they have the freedom and responsibility to build and improve those products in a sustainable way. In the past two years, we have improved the full-stack team structure by recruiting more product designers and product managers. There is now one product manager per team, and one product designer supports one to three teams on average. We have also been strengthening design thinking and giving product design a more central role in product development.
Now that we have more than double the number of teams compared to two years ago, we have found that we need to find a more reasonable balance between what ways of working we standardize across teams and what teams can choose on their own. It’s not feasible to guide each team individually, so we have looked for ways to steer the whole ship in the same direction instead.
The development teams have a lot of decision-making responsibility, and sometimes it may feel a little overwhelming. Adding layer of basic principles to the working agreements helps teams align their thinking with the general direction of the whole company. For example, one of our core principles is Collaboration over silos. We believe that generating a shared understanding is more valuable than the short term wins gained by solo projects. It also means that no part of the product development cycle should be a handover, but have a tight feedback loop between the agents performing the different steps.
While we allow development teams a lot of autonomy in choosing their ways of working, we want to be somewhat opinionated as to what are our preferred ways of building the product. Because one of our core principles is that we are here to solve our customers’ problems, we try to build minimum vertical solutions that produce value to our customers. We also want to push these solutions to production early on to get the feedback loop going, instead of trying to build massive releases that seek to do everything at once. At the same time, we don’t want to build features just for the sake of producing code, so we set clear expectations to the usage and measure if we meet those expectations.
The old working agreements didn’t make a clear distinction between binding rules and best practices that teams could either follow or discard. This ambiguity diluted the working agreements, so this time we paid extra attention to determining what we need to agree on the organizational level, and where each team can define their own approach. In short, we set out to find the best ratio of standardization and customization.
Sharing information openly between teams is something we want to stick to regardless of the size of the engineering team. Transparency needs to be routine, and that’s why we have agreed to share meeting notes in our internal chat and tag them for easy retrieval. We have also agreed to track epics, stories, and bugs in JIRA to collect the information that all teams need access to into one organization-wide communication channel. However, for monitoring team-specific tasks, the development teams are free to choose their approach and tools. Some teams use JIRA for tasks too, while others use physical kanban boards and post-it notes.
As the organization is growing, we felt it was essential to clarify the different roles (developer, team lead, product designer, and product manager) and their responsibilities within the development teams. For example, a product designer is responsible for flagging usability issues in the team’s responsibility areas, and developers are responsible for technical solution design.
Agreeing on responsibility areas on a high level doesn’t mean that they are chiseled in stone. Actually, we believe that in healthy teams, these activities are decentralized. For example, while the product manager is responsible for providing the customer perspective, everyone should have an understanding of customer needs in a well-functioning full-stack team. Similarly, the team lead is responsible for making sure the team works efficiently, but everyone should feel ownership of the team, raise issues, and help fix problems together.
Even though our product organization has grown significantly during the past two years, we want to stick to our end-to-end full-stack teams and mandate as little process as possible to increase team autonomy. Our teams own their roadmaps, make decisions on how to improve their product area, and choose how to implement those improvements.
While our ways of working have evolved to support a larger team and a more complex product, they are still driven by largely the same principles as before. We are still on the mission to simplify things as much as possible, and avoid adding rules and processes for the sake of rules and processes.
The work is by no means finished. We still need to find new ways to support transparent communications across all the development teams, and steer clear from siloing. We also need to keep exploring the best ways to reduce dependencies between teams while at the same time setting up more platform-like teams that build solutions that other teams use. Even after we finish this round of refreshing the working agreements, we’ll need to keep a sharp eye on how well they support our evolving organization and reiterate them when needed.