
Summary
Many software-based organizations have migrated their monolithic applications software to microservice systems for faster delivery, higher quality, easier scalability, etc., to become more agile and competitive. For instance, in 2008, Netflix, a movie-streaming provider, experienced a three-day outage and was unable to sell DVDs due to the monolithic structure of its codebase. In response, Netflix scaled its streaming service by migrating its monolith to an MSA comprising 700+ services and handling 15 billion API calls daily worldwide.
Yet, our research shows that migrating to microservices is the beginning of the journey rather than the end goal. Even after migration, maintaining different microservices still involves synchronization overhead among different teams. We conducted a study on one of the most popular cloud providers, OpenStack, to understand the extent to which different services can depend on each other in terms of maintenance. For instance, are changes to different microservices, managed by different teams, dependent on each other? If the dependency among components increases, does it involve changing the architecture (e.g., removing projects)? If so, does changing the architecture help mitigate the number of dependencies among changes? Our findings reveal that adopting a modern architecture is not an end goal: services can still depend on each other, and developers may need to coordinate across teams to resolve issues. Project restructuring can help control the number of dependencies among different teams. We are distilling lessons learned on dependency management for practitioners and researchers to enhance the maintenance and evolution of multi-component systems.
Keywords: software maintenance, software evolution, modularity, empirical study
Migrating to MSA Might Not Be an End Goal
Modern software systems typically comprise several loosely coupled components that are developed, maintained and deployed independently. Teams are often responsible for their respective components, and are expected to work autonomously without frequent synchronization. This architectural style offers a key advantage: improved time-to-market, enabling fast and secure software delivery. When a component changes to meet evolving requirements, only that component needs to be deployed, without affecting the operation of other services. While this is the theory, does it apply in practice?
In this work, we conducted an empirical study of source code changes submitted to OpenStack, an open-source, cloud-based solution. To identify dependencies between services (i.e., changes to different services that depend on each other), we leveraged four tags that developers mention in their change descriptions: “Depends-On,” “Needed-By,” “Change-Id,” and “Related-Bug.” “Depends-on” means that one change depends on another change. “Needed-by” means that one change is required for another change. Some related changes share the same “Change-Id.” Multiple changes may fix the same bug or implement the same feature indicated by the “Related-Bug” tag.

It is often believed that migrating a monolithic application to microservices is an off-the-shelf solution to the problems encountered by practitioners in legacy systems. However, the literature and our study tell a different story. Post-migration services can still exhibit interdependencies spanning multiple teams. Roughly 10% of OpenStack changes cross project boundaries, and roughly 6% cross team boundaries—with knowledge, background and context differing from one team to another, as illustrated in Figure 1. Practitioners working on large-scale systems should therefore expect a degree of service coupling and team coordination, even after migration.

Practitioners should also be cautious about the frequency of interdependencies and their potential growth over time, as shown in Figure 2. We observed increasing dependencies among services, particularly in the first six years of OpenStack, peaking in 2016. When dependencies reach certain thresholds, teams should be equipped with automated tools to monitor, manage and mitigate their system-wide impact.
To minimize dependencies among services, practitioners should consider restructuring projects when needed, even in multi-component systems. A modular architecture may not be a lifelong solution. We recommend restructuring components that show a large number of cross-component changes. For instance, we observed that the number of cross-component changes increased over time, peaking in 2016, then decreased after a large number of projects were archived. This large-scale refactoring also reduced the number of external projects a given project depended on.
Keeping track of dependencies over time may help reduce unexpected cross-project relationships. One practical step is to track the rate of interdependencies per project. When a project begins to depend on several others, maintainers can investigate underlying factors early, saving time and reducing maintenance overhead. Practitioners could also consider additional migrations or restructurings based on the number of files that trigger external dependencies. For example, if files in one project regularly cause changes in several other projects, this may indicate the need to split the project into smaller, independent sub-projects with low coupling and high cohesion.
Conclusion
Overall, we find that migrating to microservices is not necessarily a lifelong solution. Services can continue to depend on each other, and such interdependencies have increased over time, particularly in the early project stages. Practitioners should pay close attention to such behavior. Cross-team coordination may also be required, which is challenging in large-scale systems with hundreds to thousands of services managed by different teams. We recommend that practitioners not neglect dependencies, as they can quickly grow over time, potentially leading to removing a large number of microservices. Furthermore, monitoring interdependencies and detecting early signs can help determine when to restructure a system or consider another migration.
Additional information
For more information about this work, we refer the readers to: Arabat, A., & Sayagh, M. (2024). An empirical study on cross-component dependent changes: A case study on the components of OpenStack. Empirical Software Engineering, 29(5), 109.
References
Sampaio et al. “Supporting microservice evolution.” International Conference on Software Maintenance and Evolution (2017).
Bogner et al. “Assuring the evolvability of microservices: insights into industry practices and challenges.” International Conference on Software Maintenance and Evolution (2019).