Modular Monolith vs Microservices: How to Choose
Modular monolith vs microservices: start with a modular monolith and extract services only when a real force demands it. The decision framework and the signals.
Part of Microservice Service Design: Boundaries That Hold
Modular monolith vs microservices has a clear default answer for almost every new system: start with a modular monolith, and extract microservices only when a specific force demands it. The modular monolith gives you most of the discipline of good service boundaries, strong module separation, clear ownership, without paying the network latency, operational complexity, and distributed-systems failure modes that microservices impose from day one.
The industry over-rotated on microservices and many teams adopted them before they had the problems microservices solve. The result was distributed monoliths: all the cost of services, none of the independence. The corrective is not “monoliths good, microservices bad” but “earn your way into microservices.”
Why this is the most consequential architecture choice
The monolith-versus-microservices decision shapes your deploy model, your team structure, your failure modes, and your operational cost for years. It is also the decision most often made for the wrong reasons, resume-driven development, hype, or a belief that microservices are simply more “scalable,” rather than a real, present need.
Getting it right early saves enormous pain, because reversing it is expensive in both directions: splitting a tangled monolith is hard, and re-merging premature microservices is harder. This post is part of the Service design series.
What is the difference between a modular monolith and microservices?
A modular monolith is a single deployable application with strong internal boundaries between modules; microservices take those same modules and run them as independently deployable services that communicate over the network. Both demand real boundaries. The difference is what crosses them: in a monolith, an in-process function call; in microservices, a network call with all the latency, partial failure, and serialization that implies.
| Modular monolith | Microservices | |
|---|---|---|
| Deploy unit | One application | Many independent services |
| Module calls | In-process (fast, reliable) | Network (latency, partial failure) |
| Boundaries | Enforced in code | Enforced by the network |
| Refactoring boundaries | Cheap (move code) | Expensive (re-split services) |
| Independent scaling | No (scale the whole app) | Yes (scale per service) |
| Operational complexity | Low (one thing to run) | High (mesh, tracing, deploys) |
| Team autonomy | Shared deploy | Independent deploys |
The key insight is that the modular monolith and microservices share the most important property, real module boundaries. A well-built modular monolith is not spaghetti; it is microservices’ boundary discipline without the network tax. That is what makes it the right starting point and a clean springboard to extract services later.
Should you start with a monolith or microservices?
Start with a modular monolith for almost every new system. Early on you do not yet know where the right service boundaries are, because you do not yet fully understand the domain, and a monolith lets you move boundaries with a refactor instead of a cross-service migration. Locking in service boundaries before you understand the domain is how you end up with the wrong services and a distributed monolith.
The modular monolith also keeps the door open. Because its modules already have clean boundaries, extracting one into a service later is a contained operation, not a rewrite. You get the option to go distributed without paying for it before you need it.
When should you move from a modular monolith to microservices?
Extract a microservice when a concrete force appears that the monolith cannot satisfy, and extract only that service for that specific reason. The legitimate forces are independent scaling, team autonomy, fault or security isolation, and a genuinely different technology need for one component. “It would be more modern” is not on the list.
The real triggers for extraction:
- Independent scaling. One component has a wildly different load profile and needs to scale on its own.
- Team autonomy. A team needs to deploy on its own cadence without coordinating with the rest of the app.
- Fault isolation. A risky or heavy workload should not be able to take down the whole application.
- Security isolation. A component handles sensitive data or untrusted input and needs a separate boundary.
- Different technology. One piece genuinely needs a different language or runtime, like a Rust hot path.
When one of these appears, extract that single module into a service, because that module has that need. Do not use it as a reason to dissolve the whole monolith. The strangler-style, one-service-at-a-time extraction is how mature systems migrate, and it keeps you in control the whole way.
Is a modular monolith better than microservices?
For most teams at most stages, starting with a modular monolith is the better call. It delivers the boundary discipline that makes microservices valuable, while avoiding the network latency, operational overhead, and distributed-systems failure modes that microservices add. Microservices are better, specifically, when you have the forces above, which is a narrower set of situations than the last decade of hype suggested.
The honest tradeoff is independence versus simplicity. Microservices buy independent deployment, scaling, and isolation, and they pay for it with cross-service boundaries that break in subtle ways, distributed tracing, and a much heavier operational footprint. A modular monolith keeps things simple and gives up that independence until you actually need it. Choose based on which set of problems you have right now, not which architecture sounds more advanced.
Does a modular monolith scale?
Yes, much further than most teams assume. A single well-built application on modern hardware, scaled horizontally behind a load balancer, handles very large traffic, and the database is almost always the real scaling limit long before the application tier is. “We need microservices to scale” is usually a misdiagnosis; what most systems actually need first is a faster data layer, caching, and more instances of the same monolith.
The distinction that matters is between scaling throughput and scaling independently. A monolith scales throughput fine by running more copies of itself, which is simple and effective. What a monolith cannot do is scale one component independently of the rest, so if a single subsystem needs ten times the resources of everything else, running ten times as many full monoliths to feed it is wasteful. That specific inefficiency, not raw capacity, is a legitimate trigger to extract that subsystem.
So the honest answer is that scaling is rarely the reason to leave a monolith; independent scaling of an imbalanced component sometimes is. Diagnose which one you actually have before splitting. Many teams adopt microservices for “scale” and discover their bottleneck was the database all along, which microservices did nothing to fix and in fact made harder to reason about.
A modular-monolith-vs-microservices checklist
Use this when deciding for a new system or component:
- Default to a modular monolith with real, enforced module boundaries.
- Confirm you do not yet have a concrete force requiring independent services.
- If you do, name the specific force (scaling, autonomy, isolation, technology) for the specific component.
- Extract that one component as a service, not the whole system.
- Keep module boundaries clean in the monolith so future extraction stays cheap.
- Re-evaluate as the domain and team grow; the right answer changes over time.
- Avoid splitting on hype, resume-building, or a vague sense that services are “more scalable.”
What I’d do differently
The mistake the whole industry made, and I have made, is reaching for microservices as the default for greenfield systems because they signaled scale and sophistication. The cost was distributed monoliths: teams paying the full operational price of services while still being unable to deploy independently, because the boundaries were wrong.
If I were starting a new system today, I would build a modular monolith with boundaries as disciplined as if they were services, and I would extract services only when a real, named force appeared, one service at a time. That path gives you simplicity now, the option of distribution later, and the best chance of getting boundaries right, because you draw them after you understand the domain rather than before. Microservices are a tool for specific problems, not a maturity level you graduate to.
Sources
- Martin Fowler, MonolithFirst: martinfowler.com/bliki/MonolithFirst.html
- Martin Fowler, Microservice Premium: martinfowler.com/bliki/MicroservicePremium.html
- Sam Newman, Building Microservices (when to split): samnewman.io/books/building_microservices_2nd_edition
Frequently asked questions
What is the difference between a modular monolith and microservices?
A modular monolith is a single deployable with strong internal module boundaries; microservices split those modules into independently deployable services over a network. Both enforce boundaries, but the monolith keeps one deploy and in-process calls, while microservices add independent deploys at the cost of network calls and operational complexity.
Should you start with a monolith or microservices?
Start with a modular monolith for almost every new system. You rarely know the right service boundaries early, and a monolith lets you move them cheaply. Extract microservices later, when a specific force (independent scaling, team autonomy, isolation) actually demands it.
When should you move from a modular monolith to microservices?
When a concrete force appears: a component needs to scale independently, a team needs to deploy without coordinating, a workload needs fault or security isolation, or a part needs a different technology. Extract that specific service for that specific reason, not the whole system at once.
Is a modular monolith better than microservices?
For most teams at most stages, yes to start. A modular monolith delivers much of the boundary discipline of microservices without the network and operational tax. Microservices win when you genuinely need independent deployment, scaling, or isolation, which is a smaller set of cases than the hype suggests.