Effective team collaboration and code ownership for managing microservices systems

Published by Emre Baran on January 20, 2025
Effective team collaboration and code ownership for managing microservices systems

Transitioning from a monolithic architecture to microservices is an intricate, time-consuming task. It demands both strategic foresight and meticulous execution.

In this 10-part series, we’ll guide you through the most common challenges faced during monolith to microservices migration. Last week we published the ninth article in our ten-part series covering the organizational and cultural shifts that come with the transition. This week, we’re publishing the tenth, and final article in our series. In it, we’ll cover team collaboration and code ownership.

If you’d like to start from the beginning, you can start with the first post on "How to determine service boundaries and decompose your monolith when migrating to microservices" or, you can download the complete 10-part series in one e-book now: "Monolith to microservices migration: 10 critical challenges to consider"

Team collaboration and code ownership brief intro

Team collaboration and code ownership are important in every architecture, but when you decompose your monolith, they become essential throughout your organization.

Microservices are typically developed and managed by multiple teams, each of which is responsible for their own specific services or domains. These teams not only have to collaborate to build and maintain an app, but the members of each team have to work together without recourse to an outside judge.

This autonomy requires effective collaboration and clear code ownership for every developer. And for those at the top, it requires a lot of trust in your teams. But that doesn’t mean you have to sit on the sidelines hoping for a good result. When you take the time to set up team structures that work in this new context, you position your teams for success. That starts with re-organizing your team.

Organizing teams to excel

Much like the services they run, microservices teams are often organized around business capabilities or domains rather than technical layers. This is known as "vertical slicing". It allows teams to have end-to-end ownership of their services, from development to deployment and maintenance. This builds cross-functionality into the team and gives them the freedom to make the best choices for their particular service.

Depending on the goals of your teams, there are a variety of ways you can choose to vertically slice them.

  • Feature teams are responsible for developing and maintaining a specific set of features or business capabilities.
  • Some companies choose to create domain-driven teams by aligning each with specific business domains or subdomains following the principles of DDD.
  • Stream-aligned teams are organized around the flow of work, such as user journeys or data streams, allowing for end-to-end ownership and faster delivery.

Organizing teams to excel - microservices.png

These teams need to stay agile, so it’s best to keep them small. The "two-pizza team" rule, popularized by Amazon, is an effective rule of thumb to follow when putting together teams. The two-pizza rule states that teams should be small enough to be fed with two pizzas, typically consisting of 6–8 members.

Giving teams ownership of their code and repositories

Each team has to own their code. That means they need control of their own code repository that covers the team’s domain and boundaries of service. That often means that each service has its own repository, though not necessarily. Related services may also be grouped together in a single repository which is owned by its respective team.

Regardless of how you define the borders, clear repository boundaries are integral to enforcing access control, managing dependencies, and facilitating independent deployments. This decentralized ownership structure promotes autonomy, which, as we discussed in article 9, is an essential aspect of working in a microservices architecture.

Decentralized doesn’t mean chaotic, however. Setting a small set of foundational standards—such as basic tech stack, coding “best practices” or project structures—will allow developers to move between service teams if need arises. In the end, while the teams are independent, they’re all working towards releasing the same, integrated platform, and that common goal should be reflected in how they pursue their goals.

Facilitating communication and collaboration

Teams need to establish clear communication channels and practices to share knowledge, coordinate efforts, and resolve dependencies. That doesn’t happen by accident.

You can help your team develop good habits by instituting a variety of techniques, like:

  • Scheduling regular cross-team check-ins where everyone can share updates, discuss challenges, and align on common goals.
  • Establishing knowledge-sharing sessions around specific technical or domain areas so teams can share best practices, learn from each other, and maintain consistency across services.
  • Encouraging teams to document knowledge, including their services, APIs, and best practices. Wikis, knowledge bases, or shared repositories can be effective tools for this.

Setting API contracts and service agreements

In the same way that your teams need to communicate, your services do as well. In microservices architectures, that means establishing clear API contracts and service agreements.

Well-defined expectations for inputs, outputs, and behaviour of a service's API create a shared understanding between the service provider and consumer teams which allows your services to collaborate easily and reduces dependencies between teams. When API contracts inevitably need to change, the revisions must be communicated and versioned properly to avoid breaking dependencies and communication.

Service level agreements (SLAs) will help your team set expectations and define the responsibilities of each team in delivering and consuming services.

Leveraging continuous integration and continuous delivery

With multiple teams across your application updating services separately, and keeping everyone up-to-date with each node, and ensuring integration through updates becomes an almost overwhelming task.

That’s why most teams who use microservice architecture deploy some form of Continuous integration (CI) and Continuous Delivery (CD) pipelines. These automate the build, testing, and deployment processes, so teams can frequently integrate their code changes, and deploy services independently, allowing for efficient collaboration.

As every team needs the ability to work autonomously, each team should have its own CI/CD pipeline. This way they can develop, test, and deploy their services without worrying about what other teams are doing. Pipelines should be configured to run automated tests, perform code quality checks, and deploy services to the appropriate environments based on predefined criteria.

Leveraging continuous integration and continuous delivery.png

Humans are complex. So, changing team culture is often more difficult than changing technical practices. But that doesn’t mean it’s impossible. Spotify is a great example of a company that managed to create a lasting change in their culture when they shifted to a microservices architecture.

Organizing cross-company communication with Spotify

When Spotify decomposed its monolith, it also decomposed its hierarchy to create a flatter, more collaborative team culture. This major shift offers great lessons on how to encourage your people to change by increasing communication.

Organized in squads and tribes

While Amazon has their ‘two pizza’ rule, Spotify has its squads. Like ‘two-pizza’ teams, squads are small. But they’re also defined by more than just their size. They’re cross-functional teams that own and develop specific features or services. Each squad has the autonomy to make their own decisions, choose their own technologies, and deliver value independently.

These squads are then grouped into tribes based on how closely related their areas or domains are. Tribes provide a forum for squads to come together to share knowledge, align on best practices, and coordinate efforts so that they don’t become silos.

By creating different levels of organization, and implementing practices that bring them together, Spotify gives each of its teams a high degree of autonomy while still bringing them together.

Maintaining a plethora of clear ownership boundaries

Spotify uses a microservices architecture with hundreds of services, each owned by a specific squad. Each of those squads has the freedom to choose the programming languages, frameworks, and tools that best suit their needs as they develop and maintain their service.

This creates a dizzying array of technologies and frameworks. All the services, irrespective of ownership, are stored in a single repository using a monorepo approach. But they don’t all get tossed together without concern for teams or services.

Each squad has its own dedicated folder within the monorepo to maintain clear ownership boundaries.

Creating opportunities to meet new people and learn skills

Formally, all developers are grouped into squads and tribes at Spotify, but the groups don’t end there. Spotify encourages all developers to build bridges beyond their squad/tribe with a variety of collaboration practices.

  • Guilds, which are communities of interest, are open to people from all different squads and tribes. These groups host meetings where anyone interested can come to share knowledge and discuss specific topics. These topics could include web development, data engineering, agile practices, etc.
  • Developers can also join “chapters”, which are groups of people with similar skills or expertise, such as front-end developers or data scientists. Chapters provide a forum to share best practices, learn from others, and maintain technical excellence.
  • Tribes also hold regular meetings to discuss high-level goals, share updates, and coordinate efforts among the squads within the tribe.

API contracts and service agreements

Each squad at Spotify is responsible for designing and documenting their APIs, allowing them autonomy. These API specifications are stored alongside the code in the squad's folder in the mono repo. Any changes to those API specifications need to be reviewed by the relevant squads before being put into action. They are accountable for ensuring backward compatibility and avoiding breaking changes.

However, the squads aren’t given a full blank slate. Each is required to follow consistent guidelines and standards to ensure compatibility and a shared understanding between them.

In the same way, Spotify defines standards for service level objectives (SLOs), including expected performance, availability, and reliability targets. Squads are then responsible for monitoring and meeting these SLOs.

Continuous integration and delivery

The squad’s autonomy continues through to their CI/CD pipeline. They use tools like Jenkins, Travis CI, and Spinnaker to automate their build, testing, and deployment processes. This enables them to continuously integrate code changes, run automated tests, and deploy services independently.

Code reviews and pair programming are common practices within squads to maintain code quality, share knowledge, and foster collaboration.

As they rebuilt their architecture, Spotify also rebuilt their team organization, which is a large part of why their migration was so successful. Through the squad model, Spotify has created a highly collaborative and efficient development environment that many other companies are constantly trying to replicate across the world.

Switching to microservices can be tricky, but if you're ready for the challenges and plan ahead, you can increase your chances of success. The key is being open to the cultural changes, getting different teams to work together, leveraging best practices and tools, so your team can navigate this transition effectively. It's not going to be simple, but stick with it and be willing to adapt as you go.

The journey to microservices takes time and you'll be learning a lot along the way, but if you can navigate that, the benefits of this new way can really pay off.

Parting thoughts

This is the last chapter in our series on the top 10 organizational and technical challenges when migrating from a monolith to microservices.

If you’d like to start from the beginning, you can start with the first post on "How to determine service boundaries and decompose your monolith when migrating to microservices" or, you can download the complete 10-part series in one e-book now: "Monolith to microservices migration: 10 critical challenges to consider"

Book a free Policy Workshop to discuss your requirements and get your first policy written by the Cerbos team