Microservices are often presented as the obvious solution for any system that needs to grow. The pitch is compelling: each service is small and focused, teams can work independently, deployments are faster, and individual components can scale on demand. On paper, it seems like the natural evolution of how large software should be built.
I had the chance to experience this first hand, working on a recommendation service for a marketplace project built by 150+ developers across 35 teams. Here is what it actually looks like from the inside.
Recommendation System
The Setup #
The project used LeSS (Large-Scale Scrum), a framework for scaling Scrum across multiple teams working on a single product. Each team had a product owner, a scrum master, and three to four developers, with an overall product owner maintaining the full picture. Every team was assigned a specific feature or area of the product to build independently.
In theory, it should have worked well. In practice, it was much harder.
The Problems #
No clear direction from the start #
One of the first issues was that each team ended up defining its own goals instead of working from a shared top-down vision. In some ways, teams were acting as both the developers and the clients, writing requirements and building them at the same time, without a real external stakeholder to validate against. That tension never fully went away.
Services were not as independent as expected #
Despite the microservice model, individual services were deeply dependent on each other. A recommendation engine for a marketplace is inherently tied to the product catalog. We needed accurate, up-to-date product data to generate and enrich suggestions. Every time a seller added, edited, or removed a product, our service had to react correctly. That meant depending on the team responsible for product management to publish the right events at the right time, with the right structure.
Data moved across teams through message queues, which meant our progress was tied to whether another team had their events correctly published. One delay upstream would cascade down and block multiple other teams. The communication between teams was constant and necessary, but the channels for that communication were rarely clean or fast.
Resource costs add up quickly #
Each service running independently means each service has its own infrastructure, cloud resources, and operational overhead. With 35 teams, that adds up fast. Shared utilities and reusable components are theoretically possible in microservice setups, but in practice, without strong documentation and upfront agreement, each team ends up rebuilding the same things in slightly different ways.
The frontend problem #
A traditional microservice setup usually assumes a single unified frontend. That was not feasible here. Instead, each team built their own frontend alongside their service, following a microfrontend approach. This introduced its own complexity: CSS from one team’s frontend would leak into another, breaking styles in unexpected ways. More critically, everything had to be integrated into shared pages like the homepage. If integration breaks on that page, users cannot reach any service at all. That is exactly the kind of single point of failure that microservices are supposed to avoid.
Shared responsibility means no responsibility #
When a problem happened during integration or production, no one clearly owned it. With so many teams contributing to the same surface, responsibility was diffuse. Issues got resolved eventually, but mostly through good will and informal coordination rather than any clear ownership structure.
Lack of standardization #
If two or three teams agreed on a convention among themselves, they would follow it, but the rest of the project might never know. Without a strong mechanism for spreading decisions across all 35 teams, standards fragmented. The same problems got solved in different ways, making the overall system harder to reason about.
What I Take From It #
Microservices can genuinely work at scale, but the architecture alone does not solve the organizational challenges that come with large teams. If anything, it amplifies them. Good communication, clearly defined ownership, shared conventions, and a coherent overall vision matter more in a microservice setup than in a monolith, because the cost of misalignment is paid immediately in integration failures and cascading delays.
It is also worth being honest: not everything I described here is necessarily a microservice problem. Some of it, like the lack of direction, the diffuse ownership, and the standardization gaps, would likely have surfaced in any project with 150+ people, regardless of the architecture. The two things are hard to separate when you experience them at the same time. What microservices did was make those organizational weaknesses more visible and more costly, since every misalignment had a direct technical consequence.
The technical benefits are real: scalability, independent deployments, fault isolation. But the operational and human overhead is also real, and it is easy to underestimate when you are looking at the architecture diagram rather than living inside it.