Divided and Conquered: How the Microservices Revolution Turned Simple Software Into an Operational Nightmare
There is a particular kind of engineering confidence that precedes catastrophe. It arrives in the form of a whiteboard diagram — clean boxes connected by clean arrows — and it makes complexity look like something that can be dissolved simply by rearranging the shapes. The microservices revolution was built on exactly this kind of confidence. Break your application into discrete, independent components. Deploy them separately. Scale them individually. Let each piece do one thing well, and the whole system would become easier to understand, easier to modify, easier to trust.
That was the theory. The practice has been considerably messier.
The Architecture of Good Intentions
To be fair, the problems that microservices were designed to solve were real. By the late 2000s and early 2010s, large American technology companies were genuinely struggling under the weight of monolithic codebases — single, enormous applications where a change to the billing module could destabilize the search feature, and where deploying any update meant deploying everything at once. Netflix, Amazon, and Uber became canonical case studies for the microservices alternative, and their apparent success gave the architectural pattern a credibility that spread rapidly across the industry.
What spread less quickly was the context. These companies had engineering organizations numbering in the thousands, dedicated platform teams whose sole purpose was building the internal tooling necessary to manage distributed systems at scale, and the financial resources to absorb years of operational learning. The architecture that worked for them worked precisely because they had built the scaffolding to support it. For everyone else, the scaffolding came later — if it came at all.
What Decomposition Actually Costs
The central promise of modularity is that isolating components reduces complexity. In a narrow technical sense, this is occasionally true. A single microservice, considered in isolation, is often simpler than the equivalent section of a monolithic codebase. The problem is that software is never considered in isolation. It runs in production, it communicates with other services, it fails in ways that propagate across boundaries, and it must be understood by engineers who are trying to diagnose problems under pressure at inconvenient hours.
When a monolithic application fails, the failure is typically contained within a single process. A stack trace points to a line of code. The chain of causality is visible. When a distributed system of forty microservices fails, the failure is a conversation — a request that entered the system, touched a dozen services, encountered a timeout in one, triggered a retry storm in another, and eventually surfaced to the user as an error message that reveals nothing useful. Reconstructing what actually happened requires correlating logs across multiple systems, interpreting distributed traces that may themselves be incomplete, and possessing a mental model of service interactions that no single engineer is likely to hold in its entirety.
This is not a theoretical concern. Engineering teams across the industry have quietly begun acknowledging what the conference circuit has been reluctant to admit: that operational complexity in heavily decomposed systems has outpaced the tooling designed to manage it, and that the cognitive burden placed on individual engineers has grown substantially as a result.
The Glue Code Economy
Perhaps the most underappreciated consequence of aggressive componentization is the infrastructure it demands. Microservices do not communicate through goodwill. They require service discovery mechanisms, API gateways, load balancers, circuit breakers, message queues, distributed tracing systems, centralized logging pipelines, and container orchestration platforms. Each of these is itself a complex piece of software that must be deployed, configured, monitored, and maintained.
The result is a layered architecture where the glue holding the system together has become more sophisticated — and more operationally demanding — than the services it connects. Organizations that adopted microservices to reduce the complexity of their application layer frequently discover that they have simply relocated the complexity into their infrastructure layer, where it is less visible but no less consequential. A team that once maintained one large application now maintains one large application's worth of business logic plus an entire distributed systems platform to run it on.
The financial implications follow directly. Cloud providers have benefited enormously from this dynamic. Running forty services is not forty times cheaper than running one — it is, in most configurations, substantially more expensive, because each service carries its own compute overhead, its own network egress costs, and its own observability requirements. The economics of microservices at modest scale frequently favor the monolith, a fact that has become increasingly difficult to ignore as infrastructure budgets have tightened across the industry.
When the Pendulum Moves
There are early signs that the architecture conversation is shifting. Engineers at companies including Shopify, Stack Overflow, and Amazon itself have published accounts of consolidating services, reducing the number of independently deployed components, or reconsidering the granularity at which decomposition makes sense. The term "modular monolith" — once something of an oxymoron in polite engineering company — has been rehabilitated as a legitimate architectural pattern worthy of serious consideration.
This is not a repudiation of modularity as a principle. Separation of concerns remains a sound engineering discipline, and there are genuine use cases where independent deployment of discrete components provides meaningful operational benefits. The problem was never the idea of decomposition. The problem was its elevation into an ideology — a default posture applied uniformly, regardless of team size, organizational maturity, or actual operational need.
The Lesson the Industry Keeps Not Learning
The microservices episode illustrates a pattern that recurs throughout software history with remarkable consistency: an architectural approach that solves a real problem at a specific scale gets abstracted into a universal prescription, adopted by organizations for whom it was never appropriate, and eventually produces a new generation of problems that will inspire the next architectural revolution.
The engineers who will design that revolution are, right now, building the tools to manage the complexity that microservices created. Some of them are doing genuinely impressive work. Others are adding more boxes to the whiteboard diagram, drawing cleaner arrows, and feeling that particular kind of confidence that tends to precede the next catastrophe.
The systems perspective that OSViews has long maintained is that architecture cannot be separated from the organizational and operational context in which it operates. A pattern that works at one scale, with one team structure, with one budget, and with one set of operational priorities will not automatically work anywhere else. The modularity myth was never that decomposition is wrong. It was that decomposition is always right — and that the industry, characteristically, took years of expensive production failures to begin questioning the assumption.