A modular monolith story matters because it gives teams permission not to rush into microservices just because the idea sounds modern.
In real design work, the chapter shows how module boundaries, dependency discipline, and an intentional path toward services can improve control without immediate operational overhead.
In interviews and engineering discussions, it helps talk about premature decomposition, team overload, and the false sense of maturity often hidden behind the word microservices.
Practical value of this chapter
Design in practice
Separate real domain constraints from fashion-driven “microservices first” decisions.
Decision quality
Use modular monolith intentionally when team scale and load do not justify service split yet.
Interview articulation
Demonstrate maturity: choose architecture shape by context, not trend pressure.
Failure framing
Avoid premature decomposition and operational overload of teams.
About the talk
Modular Monoliths and Other Facepalms
A walkthrough of why a modular monolith is not a new style, but a return to engineering discipline: information hiding, module boundaries, and dependencies you can verify in the build instead of just promising on a slide.
Talk
Modular Monoliths and Other Facepalms
Kevlin Henney's NDC London talk about modularity, boundaries, and the cost of distributed architecture.
Main idea
The problem is usually the boundary, not the deployment model
Microservices do not fix poor decomposition — they move it onto the network and make every mistake more expensive to operate.
A team hits a monolith that is hard to change and reaches for microservices as the cure. Here the modular monolith is not a compromise between “old” and “new” — it is a disciplined form that solves the same pain more cheaply. Henney's point is about order of operations: information hiding, module boundaries, and explicit dependency rules need to be in place before a team chooses independently deployable services. Skip that step and you get a distributed monolith: the same coupling, now over the network.
Source
Microservices
Definition of microservices and the basic trade-offs behind independent deployability.
Main points of the talk
A modular monolith is a return to engineering basics
The talk strips away the novelty: modularity, information hiding, and componentization existed long before microservices became fashionable — what changed was the packaging, not the principle.
Microservices were often used as forced partitioning
When a monolith has lost healthy boundaries, splitting it across the network feels like a fix. But a boundary the team never drew in code will not appear just because the call became remote.
The false choice is monolith versus microservices
The monolith-versus-microservices argument is a distraction: architecture is held together by the quality of boundaries, contracts, and dependencies, not by the number of running processes.
Classic decomposition principles still matter
Parnas, ADT, and component thinking are not history for its own sake — they are working tools when you have to decide where the boundary goes right now.
Distribution amplifies poor architecture
The network does not heal weak structure, it stretches it: you get a distributed monolith — the same coupling, now with network failures, latency, and an operating bill on top.
Practical takeaway: strengthen the modular monolith first
First get the modules in order inside one process, then extract services one at a time — when a specific piece has a durable reason for independent deployability.
How the idea of modularity evolved
The conversation about modules has run since the 1970s and keeps hitting the same question: where to draw the stable responsibility boundary. The names changed; the question did not.
D. Parnas - decomposition criteria and information hiding
The criterion: a module hides the decision most likely to change and holds a stable boundary. The implementation can shift without breaking its neighbors.
Liskov & Zilles - abstract data types (ADT)
Data abstraction strengthened a contract-oriented way of designing interactions between parts of a program.
Foote & Yoder - the Big Ball of Mud anti-pattern
The paper shows how a system quietly slides into a tangle of dependencies where any change touches everything at once.
Lewis & Fowler - microservices as independently deployable services
The value of microservices is tied to independent deployment, not to the label itself.
Simon Brown - the distributed version of Big Ball of Mud
When boundaries are not clear up front, distribution does not remove architectural mistakes — it makes each one more expensive to debug and operate.
Modular monolith as a return to modularity
The framing is a return to basic engineering discipline, not the arrival of a new architecture style.
Takeaways for developers
- Modularity lives in dependencies and contracts, not in infrastructure or service count — moving to Kubernetes will not add it.
- Describe architecture as dependency rules the build can check: no cycles, imports flow one way, no skipping layers.
- A boundary that exists only in a folder name is not a boundary: code, CI, and architecture tests have to hold it, or it erodes within a couple of sprints.
- Extract services only around stable business boundaries and a real need for independent deployment.
Takeaways for tech leads
- Let the modular monolith be the default and make every microservice a separate call the team has justified and agreed to pay for.
- Treat distribution as its own line item: observability, security, delivery platform, and data consistency are a recurring bill, not a one-time cost at split time.
- Manage architecture with structure metrics: dependency graphs, forbidden dependencies, cycles, and drift between modules.
- Formalize module ownership and architectural violation policy: current baseline plus a debt-reduction plan.
Practical plan for 2-4 weeks
- 1Name 3-7 module boundaries and generate a dependency graph from the codebase.
- 2Add 5-10 architecture rules to CI: layers, cycles, and forbidden imports.
- 3Set a violation baseline: no new violations, and a clear plan to reduce the old ones.
- 4Review service candidates only where there are separate SLAs, release cycles, and a clear owner for change.
When to stay in a monolith and when to extract services
Modular monolith as the baseline strategy
Until independent deployment is a durable requirement, it is cheaper to invest in module boundaries, architecture tests, and clear change ownership inside one process — same structural cleanliness, none of the network bill.
Microservices as an intentional step
Extract services when there are clear drivers for independent deployability, separate SLAs, partial scaling, and readiness to pay the cost of distribution.
Risks and limitations
- Moving to microservices without mature boundaries produces a distributed monolith: the coupling stays, and network failures, distributed transactions, and on-call duty you did not have before pile on top.
- The label “modular monolith” becomes marketing if dependency rules are not testable.
References
- YouTube - Modular Monoliths and Other Facepalms (Kevlin Henney)
- Martin Fowler - Microservices
- Simon Brown - Distributed Big Balls of Mud
- Big Ball of Mud (Foote & Yoder)
- Parnas paper (annotated copy)
- ArchUnit (Java)
- ArchUnitNET (C#)
- dependency-cruiser (JS/TS)
- import-linter (Python)
- Building Microservices, 2nd Edition (Sam Newman)
Related chapters
- Monolith to Microservices (short summary) - A practical migration playbook: Strangler Fig, Branch by Abstraction, and safe service extraction from a legacy monolith.
- Building Microservices (short summary) - Where service architecture heads after the modular-monolith phase, and which operating trade-offs you pay for once the services are actually extracted.
- Decomposition Strategies - A bounded-context decomposition flow with dependency control to avoid ending up with a distributed monolith.
- Why microservices and integration are needed - System-level framing for when microservices are actually justified and what integration surface you need to sustain.
- Learning Domain-Driven Design (short summary) - DDD foundations for domain boundaries and change ownership that make a modular monolith a stable architecture baseline.
- Evolutionary architecture in practice - How to encode architectural boundaries as fitness functions and control structural drift through CI.

