QIAOPANG.COM · SELECTED ESSAYS (2013–2026) · 260 ESSAYSBrowse Chronologically (2013 → 2026) ↗
QiaoPang · Programmers LifeSelected Essays · Systems, Craft & Agentic Era
Timeline ↗

Ten Years of Microservices: From the Ideal of Small and Beautiful to the Return of Complexity

Ten Years of Microservices: From the Ideal of Small and Beautiful to the Return of Complexity

Any sufficiently complicated C or Fortran program contains an ad hoc, informally-specified, bug-ridden, slow implementation of half of Common Lisp. — Greenspun’s Tenth Rule

At GOTO 2024, James Lewis — one of the core champions of microservice architecture — delivered a talk of real significance: “The Magic of Small and Beautiful: Ten Years of Microservices” (https://www.youtube.com/watch?v=KruVNy9Gino). It was less a technical retrospective than an architect’s deep reckoning — with the collision of ideal and reality, with the dialectic of simple and complex, with the gains and losses embedded in any technical evolution.

Ten years ago, when James Lewis and Martin Fowler co-authored that far-reaching article on microservices, they held a plain ideal: return software development to simplicity. Ten years later, standing on the high ground of cloud native and looking back along the road, we find that the ideal of simplicity has spawned unprecedented complexity. This paradox is precisely what reveals the deeper laws of software architecture evolution.

Historical Accident and Necessity: The Soil That Grew Microservices

Let us wind the clock back to 2008–2010. It was a “wild frontier” era of software development — and the eve of change.

The Weight of the Monolith

James Lewis used a startling figure to describe the monoliths of that time: “five to twenty million lines of code.” This is no exaggeration; it was bloody reality. He mentioned a European bank whose system contained 250 million lines of COBOL — a number sufficient to suffocate any modern developer.

The problem with these giant systems lay not only in scale, but in the technical debt black hole they formed:

Ten Years of Microservices: From the Ideal of Small and Beautiful to the Return of Complexity — architecture diagram

The toolchain of that era was equally ponderous: JBoss, ClearCase, WebSphere, Oracle Forms — every one of those names redolent of “enterprise-grade” heaviness. Most ironic of all: the deployment model of these application servers — build a WAR, deploy it into a container, run it — was conceptually identical to today’s Docker and Kubernetes; only the elegance of the implementation differs by orders of magnitude.

Seeds of New Thinking

Yet in this seemingly barren soil, new seeds were quietly germinating. Spring, XP, trunk-based development, AWS — technologies and practices then regarded as heresy were challenging the established order.

More important still was the collision of ideas. In 2011, at Castel Brando in Italy (a former papal holiday villa), a group of software architects gathered for a three-day unconference. Participants included Udi Dahan, Gregor Hohpe, Stefan Tilkov, and other industry luminaries. By the third day, a consensus had emerged:

Perhaps the root of the problem is not technology, but scale itself.

That insight became the origin point of microservice architecture. If big is evil, then small is beautiful. If centralization breeds rigidity, then distribution means flexibility.

Nine Characteristics: The Design Philosophy of Microservices

In 2014, James Lewis and Martin Fowler distilled nine characteristics of microservices in that famous article. They are not merely technical specifications but a complete design philosophy.

1. Componentization via Services

The most fundamental idea: components should be independently replaceable and upgradable software units. Modularity can certainly be achieved inside a monolith, but services provide stronger isolation.

James Lewis placed particular emphasis on “independent deployability.” He noted with dismay that even today, many organizations’ “microservices” must still be deployed together and tested together — a complete betrayal of the original intent.

Ten Years of Microservices: From the Ideal of Small and Beautiful to the Return of Complexity — architecture diagram

2. Organized around Business Capabilities

This is Conway’s Law in practice. Conway’s Law, proposed by computer scientist Melvin Conway in 1967: “Organizations which design systems are constrained to produce designs which are copies of the communication structures of these organizations.” Put simply, your system architecture mirrors your organizational structure. If four teams build a compiler, you end up with a four-pass compiler. Organizational structure determines system architecture, so teams should be organized around stable business capabilities rather than technical layers.

James Lewis shared an amusing anecdote: he depicted Conway as an adorable plush puppet in his talk, and received an email from Conway himself — not a protest, but thanks, because it had his grandchildren in stitches.

Business capabilities matter because they represent the “what” of the business rather than the “how.” An insurance company will always need actuarial services, whether by abacus or by AI; an e-commerce company will always need inventory management, whether in paper ledgers or distributed databases.

3. Products not Projects

This is perhaps the most revolutionary idea of all. The traditional project model means “build—hand off—forget,” while product thinking means “you build it, you run it, you own it.”

Amazon’s practice proved the power of this model. When a development team has to handle a production incident at three in the morning, they care a great deal more about code quality, test coverage, and observability. This is not managerial coercion but the natural consequence of ownership.

4. Smart Endpoints and Dumb Pipes

In contrast to the heavyweight integration standards of the WS-* family (the Web Services standards, including WS-Security, WS-ReliableMessaging, WS-AtomicTransaction, and friends), microservices advocate simple communication mechanisms. WS-* tried to build a complete enterprise-grade service ecosystem atop SOAP and XML; the result was a complexity explosion — the configuration files alone were enough to deter anyone. The microservice philosophy is entirely different: business logic belongs inside services, not in the integration layer.

Ten Years of Microservices: From the Ideal of Small and Beautiful to the Return of Complexity — architecture diagram

James Lewis singled out Level 3 REST maturity — HATEOAS (Hypermedia as the Engine of Application State). It lets the server guide the client’s interaction flow, enabling true late binding.

5. Decentralized Governance

Autonomous teams should be empowered to choose the technology stack best suited to their problem domain. But James Lewis readily admits that their original article overemphasized freedom of technology choice while neglecting how to achieve effective decentralized governance.

He cited the core idea of Turn the Ship Around: “Don’t move information to authority; move authority to where the information is.” That requires appropriate guardrails and constraints, so that teams can decide freely within boundaries.

6. Decentralized Data Management

Each service manages its own data, breaking the traditional shared-database model. But this brings the challenge of distributed transactions.

James Lewis’s advice is simple and profound: “Prefer a larger service boundary over distributed transactions.” The CAP theorem became required knowledge for every microservices architect, even though Google claims to have solved the problem with atomic clocks — but that’s Google, not the rest of us.

7. Infrastructure Automation

Though the 2014 article gave it little space, infrastructure as code has since become a key factor in microservice success. Servers should be treated as immutable infrastructure. When an update is needed, rather than patching the existing server, you destroy the old one and rebuild the environment entirely from code. This eliminates “configuration drift” and ensures that production matches test. In today’s cloud-native era, it has become standard practice.

8. Design for Failure

“Any socket, process, pipe, or remote procedure call can fail” — such is the brutal reality of distributed systems. Netflix’s Chaos Monkey pushed this idea to the extreme: deliberately inject failures to guarantee the system’s antifragility.

9. Evolutionary Design

Software architecture is the set of decisions that are important and hard to change. But with the rise of cloud computing, many former “architecture decisions” are now just a few lines in a configuration file.

James Lewis offered an amusing metaphor for evolutionary design: imagine every technical decision as a fork in the road — choose one path and you close off the possibilities of the others. He calls this “the reality pants of infinite forking”: every line of code shapes the system’s future direction, either creating new options or foreclosing them. The key is to preserve enough optionality when deciding, to keep flexibility for unknown change.

Reflections in the Cloud-Native Era: The Loss of Simplicity

Ten years on, the microservice idea has taken deep root, but the results in practice are full of irony.

The Tool Explosion

The CNCF (Cloud Native Computing Foundation) landscape (https://landscape.cncf.io/) has become a map that leaves your eyes spinning.

CNCF Landscape

James Lewis half-jokingly quoted the XKCD comic (https://xkcd.com/1629/): “I built a tool to build tools, and those tools monitor the code of the deployment tools, and those deployment tools build the tools used to deploy the monitoring tools…”

XKCD 1629

The figure below shows how the tooling changed from 2014 to 2024:

Ten Years of Microservices: From the Ideal of Small and Beautiful to the Return of Complexity — architecture diagram

The Accidental Migration of Complexity

Martin Fowler once said that microservices shift accidental complexity into infrastructure. What actually happened is more profound: we did not merely move complexity — we invented new categories of it.

The service mesh took over many responsibilities that applications once carried — authentication, authorization, TLS termination, load balancing. It was supposed to simplify development; in practice it created a new learning curve and a new operational burden.

Lambda Pinball

Serverless computing promised ultimate simplification: just write functions, and the platform handles everything else. But James Lewis warned of the “Lambda pinball” anti-pattern: hundreds or thousands of functions calling one another, forming a spaghetti architecture that is hard to understand and hard to debug.

The Mess of Infrastructure as Code (IaC)

Even after a decade, infrastructure as code is still “a mess.” Terraform, Pulumi, CDK, Ansible — each tool has its own philosophy and syntax. James Lewis said frankly: “This is an unsolved problem; whoever solves it will be doing us all a great favor.”

Deep Thinking: What Is the Essence of Microservices?

At the heart of the talk, James Lewis revealed a more fundamental insight: microservices are not about technology; they are about organizations and people.

This insight touches the core paradox of software architecture. We always discuss microservices in technical terms: containers, API gateways, service discovery. But the real challenge lies in the limits of human cognition and the social dynamics of organizations. Conway’s Law tells us that system architecture mirrors organizational communication structures. But microservice practice reveals a deeper truth: our architectural choices are, in essence, an acknowledgment of and compromise with human cognitive capacity.

Microservice architecture is fundamentally a socio-technical design pattern that attempts to manage human and organizational complexity through technical boundaries.

The Power of Stupidity

James Lewis admitted the reason he puts services in separate Git repositories: “Because I’m stupid.” He was really confessing a universal human weakness: we cannot resist the urge to optimize and refactor, even when that urge destroys system boundaries. Physical separation becomes a tool against human nature.

This idea of “designing for stupidity” runs through the whole microservice philosophy. It is not because we are clever that we need microservices; on the contrary, we are acknowledging our own limitations:

  • The finiteness of cognitive load: the human brain cannot juggle too much complexity at once
  • The exponential growth of communication cost: as team size grows, coordination costs rise exponentially
  • The danger of diffusion of responsibility: when everyone is responsible, no one actually is
  • The psychology of fear of change: in large systems, any change may bring unforeseen consequences

So we physically separate things, to better manage boundaries and manage complexity.

The Price of Independence

Yet true independent deployment carries a heavy price:

  1. The complexity of versioned APIs
  2. The ongoing burden of backward compatibility
  3. The infrastructure investment in distributed tracing
  4. The business compromises of eventual consistency

Many teams find these costs exceed what they can bear, and fall back to the “distributed monolith” — microservices on the surface, but still requiring coordinated deployment underneath.

The Migration of Cognitive Load

Microservices do reduce the cognitive load of any single service, but they create new system-level cognitive load:

  • Understanding the interaction patterns between services
  • Debugging request paths that cross services
  • Managing state consistency in a distributed system
  • Handling network partitions and partial failure

Is this migration worth it? The answer depends on the organization’s scale, the team’s maturity, and the business’s complexity.

Lessons Learned: Wisdom After Ten Years

What Proved Right

  1. Organizing around business capabilities: organizing teams around business capabilities rather than technical layers has stood the test of time.

  2. Product thinking: “You build it, you run it” fostered better engineering practice and stronger ownership.

  3. Evolutionary architecture: keeping architecture evolvable and preserving options for the future is crucial in a fast-changing technical environment.

  4. The importance of automation: without automation, microservices are a nightmare. That judgment was entirely correct.

What Was Overlooked

  1. The importance of the cloud: the 2014 article barely mentioned the cloud — a huge omission in hindsight.

  2. Continuous delivery as a prerequisite: CD should not be optional; it should be a precondition for microservices.

  3. The difficulty of independent deployment: the difficulty of achieving true independent deployability was severely underestimated.

  4. The complexity of data management: distributed data management is far harder than expected.

What Needs Rethinking

  1. Service granularity: “micro” may be the wrong prefix. The right size is “just right,” not “as small as possible.”

  2. Technical heterogeneity: the cost of stack diversity often exceeds its benefit. Standardization may be the better choice.

  3. Sync vs. async: overuse of asynchronous communication produces system behavior that is hard to reason about. Synchronous calls remain the right choice in many scenarios.

The Next Ten Years

The Rise of Platform Engineering

Developer experience platforms (such as Spotify’s open-source Backstage) represent a new level of abstraction: not hiding complexity, but providing tools to manage it. Backstage is a unified developer portal that brings the service catalog, documentation, monitoring, deployment pipelines, and other tools together into a single interface, letting developers better understand and manage the microservice ecosystem. This may be the next stage of microservice evolution.

Microservices in the Age of AI

As AI coding assistants proliferate, some of the traditional advantages of microservices may be re-evaluated:

  • If AI can understand a million lines of code, do we still need small services?
  • If AI can refactor automatically, is independent evolution still so important?
  • If AI can generate integration code, is API versioning still a burden?

A Return to Simplicity?

James Lewis closed the talk with Erlang — a language truly designed for distribution, fault tolerance, and concurrency. Perhaps in the next decade we will see more “natively distributed” stacks, rather than forcing distribution onto traditional technologies.

Personal Reflections: Finding Balance in Complexity

Having listened to James Lewis’s talk, I have a few deep takeaways:

1. No Silver Bullet, Only Trade-offs

Microservices are no silver bullet; they merely trade one kind of complexity for another. The key is to recognize that trade clearly and make sure it fits your particular situation.

For a startup, a well-designed modular monolith may be the better starting point. For a large enterprise, the organizational scalability that microservices provide may well be worth the extra technical complexity.

2. People and Organizations Before Technology

The key to microservice success is not Kubernetes or Istio, but organizational culture, team autonomy, and engineering maturity. If the organization still runs on waterfall, microservices will only amplify the chaos.

3. Incremental Adoption

You don’t have to accept every microservice idea wholesale. Start with one or two services with clear boundaries, and learn and adapt as you go. “Big bang” microservice transformations almost always end in failure.

4. Stay Pragmatic

James Lewis’s candor is admirable — he admits mistakes, questions his own choices, and even jokes that “microservices” is a terrible name. This pragmatism is worth emulating: technical choices should be based on actual results, not theoretical purity.

Conclusion: The Ideal of Small and Beautiful vs. the Reality of Big and Complete

Ten years ago, microservices promised a world that was small and beautiful: every service simple enough for one person to understand, teams able to work independently, systems able to evolve quickly.

Ten years later, what do we have? A tech stack more complex than ever, but also a more powerful and flexible architectural pattern. Microservices did not eliminate complexity; they changed its form, making it easier to manage — at least in theory.

As James Lewis said in his talk, microservices may not be the future, but they “are doing okay for now.” In the uncertain field of software architecture, “okay” may already be the best we can hope for.

True wisdom lies neither in blindly following microservices nor in clinging to the monolith, but in understanding the essence, the trade-offs, and the applicable scenarios of each approach. In that sense, James Lewis’s talk is not only a summing-up of the past but a revelation for the future: stay humble, keep learning, dare to admit mistakes, and always remember — the purpose of architecture is to serve people, not the other way around.

Perhaps in the next decade we will discover a new architectural paradigm, or return to some forgotten wisdom. But either way, these ten years of microservice exploration have forever changed how we think about and build software. That change goes beyond technology itself and touches the essence of software engineering: how to preserve human dignity and creativity within complexity.

That, perhaps, is the most precious legacy microservices have left us.

MORE IN Systems & Architecture

Further Reading in This Column

View all essays in “Systems & Architecture” →

The Future of Logs: Rectifying Names

For a decade we built observability into a beautiful tower on a foundation of drifting strings—field names by convention, cardinality by luck, bills by endurance. This essay proposes a radical fix: use protobuf to give every observed event a proper name, unify logs, metrics, and audit into one versioned, owner-tagged, retention-aware event catalog, and keep an escape hatch called ForensicEvent for the unknown unknowns.

New Hope (2025–2026)10,772 chars · 24 min read

Abandoning Multi-Environment Entirely: Reshaping the Next-Generation Serverless Architecture with Rust and Pingora

When we return to first principles and reconsider what "compute" really is, we find that multi-environment setups are an illusion, Kubernetes is an over-abstraction, and Serverless cold starts and connection-pool storms are self-inflicted. This essay dissects an environment-less architecture built on Baggage Header routing, a Pingora smart gateway, Firecracker microVMs, and a Rust Data Bus — an attempt to answer: what should compute look like in the post-Kubernetes era?

New Hope (2025–2026)23,788 chars · 53 min read