Monolith to Microservices: When to Migrate (and When Not)

Going from monolith to microservices used to be the default modernization path. In 2026, it's the wrong default for most teams. Knowing when to actually do it has become more valuable than knowing how. This guide is for engineering leaders and architects tired of being asked when the team is going to "move to microservices" who want a defensible answer that isn't yes by reflex.
This guide covers what going from monolith to microservices actually means (and what people usually mean when they say it), why the industry has been quietly walking back the universal-microservices position, when microservices make real sense, the modular monolith middle path that's eating most of the prior conversation, a decision framework that holds up under questioning, the strangler-fig and database-decomposition mechanics if you've decided to migrate, the anti-patterns that ruin migrations, and the architecture-decision discipline that has to sit underneath all of it.
What Does Going from Monolith to Microservices Actually Mean?
Going from a monolith to microservices means breaking a single deployable application into a set of independently deployable services, each owned by a team, communicating over the network, with separate data stores (or at least separate data ownership). It used to be the recommended path for any system that wanted to scale beyond a small team. In 2026, the recommendation is conditional.
A couple of clarifications first, because the term gets used loosely.
- A monolith is not the same as a mess. A clean, well-modularized single-deployable system is a monolith. A pile of spaghetti spread across one hundred microservices is also a mess, just a more expensive one. The structural choice and the code quality choice are independent.
- A microservice is not just a small service. A microservice is an independently deployable unit, owned by a single team, that communicates over the network. Splitting a monolith into a dozen "services" that all deploy together and share a database is not microservices; it's a monolith with extra HTTP calls.
Holding the terms steady matters because the conversation usually starts with someone arguing for microservices and someone else arguing for "keeping the monolith," and the two often disagree about what either term means. Either choice usually sits within a broader legacy system modernization program, which sets the budget and the constraints the migration must fit within.
Why the Industry Is Rethinking Microservices in 2026
The microservices wave that crested between roughly 2015 and 2022 was driven by real successes at companies operating at internet scale: Netflix, Amazon, Spotify, Uber. The lesson the rest of the industry took was that microservices were the path. The lesson that was actually being taught was more conditional.
The 2026 conversation has shifted in three visible ways.
The widely shared 2023 Amazon Prime Video case study, in which one team consolidated a specific distributed serverless workflow into a simpler single-process design and reported major cost reduction, became the most-cited "we went back" story in the category (though the framing was contested). The lesson wasn't "microservices are bad"; it was that distributed architecture has to earn its operational cost. Other engineering organizations have publicly discussed consolidating services or rethinking service boundaries, though the details vary. The pattern is consistent. The operational cost of running microservices well grew faster than the original team had estimated, and the architectural complexity was producing diminishing returns relative to the rest of the application modernization work the team was carrying out.
The modular monolith pattern (clear domain boundaries, internal modules, single deploy) has emerged as a credible middle path. The book and talk circuit around it has been busy, and the pattern now has a vocabulary that the architecture community recognizes. Teams that would have committed to microservices in 2018 are now seriously evaluating modular monoliths as the right destination, not as a stepping stone.
AI agents writing code have shifted the cost-of-complexity calculation in pretty substantial ways, too. When the cost of writing code drops faster than the cost of operating distributed systems, the relative cost of microservices' operational overhead goes up. The fix is not "everything goes back to monolith," but "the threshold at which microservices pay off has moved."
None of this kills microservices. It does mean that the default answer for new systems and for active monolith-to-microservices migrations is now "evaluate explicitly," not "yes, let's start the migration."
When Microservices Actually Make Sense (and When They Don't)
Microservices solve specific problems. Outside of those problems, they cost more than they save.
Team-Size Triggers
The most common honest argument for microservices is organizational rather than architectural. Once you have roughly 50+ engineers across multiple teams that need to deploy at different cadences, the coordination cost of shipping a monolith starts to exceed the operational cost of running distributed services. Below that scale, the math usually goes the other way. Treat the number as a heuristic, not a law; the real threshold depends on deploy cadence variance, isolation needs, and platform maturity.
Independent Scaling Needs
If a specific subsystem (image processing, recommendation, search) has a fundamentally different scaling profile than the rest of the application, separating it can pay off. The honest test is whether the scaling difference is large and persistent. Splitting a service because it's "going to need to scale" eventually almost never recovers the migration cost.
Multi-Tenant Isolation Requirements
When regulatory or commercial constraints require strict isolation between tenants or domains, a microservice architecture can make those boundaries enforceable at the deployment layer rather than only in code. This is one of the few cases where microservices are doing genuinely architectural work.
When They Don't Make Sense
If the team is below the size threshold, if the scaling needs are not differential, and if the isolation requirement can be met in-code, microservices usually cost more than they provide. The Prime Video case is the canonical example. A small team running distributed services for a problem that fits comfortably in a single process.
The Modular Monolith: The Middle Path
The modular monolith has become the answer for most teams that would have committed to microservices five years ago. The shape is straightforward: a single deployable application with clear internal module boundaries, separated data ownership (even if it shares a database physically), and a discipline that the modules communicate through well-defined interfaces rather than reaching into each other's internals.
What does this get you?
- Operational simplicity. One deploy, one set of metrics, one observability story. The platform team's cognitive load stays manageable.
- Refactoring locality. Changing a type signature is one commit, not a multi-service rollout.
- Optional decomposition later. If a specific module grows up into its own service eventually, the modular monolith has already done most of the boundary work.
But, here’s what this doesn't get you:
- Independent deploy cadences. Everything ships together. For most teams below the 50-engineer threshold, this is a feature, not a limitation. Above that threshold, it starts to bite.
- Independent scaling per module. The whole application scales together. For most workloads, this is fine. For workloads with differential scaling needs, it isn't.
The modular monolith works as a destination for many teams and as a holding pattern for others. The discipline is recognizing which case you're in. We've covered the broader system architecture framing this sits inside; the modular monolith is one specific commitment in that broader conversation.
A Decision Framework: Monolith vs Modular Monolith vs Microservices
The decision shouldn't be made by reflex. The shape that holds up under questioning looks like this.
The framework is descriptive, not prescriptive. The right column has prerequisites, the left two don't, and skipping any one of them is what produces the "we did microservices, and it broke" stories. The observability investment is not optional once services start communicating over the network. The network-resilience patterns (retries, circuit breakers, idempotency) are not nice-to-haves; they're the table stakes that distinguish a real microservices architecture from a distributed monolith.
The trap most teams fall into is reading the table left to right and assuming the right column is the destination. The honest reading is that the right column has prerequisites, the left two don't. If the observability investment, platform team, and team-size threshold aren't in place, microservices will generally cost more than they pay back.
If You're Migrating, Here's How to Do It
For the cases where microservices are genuinely the right answer, the mechanics that work are well-rehearsed.
Inventory and Identify Seams
Before extracting anything, map the application's domain boundaries. Domain-driven design vocabulary (bounded contexts, aggregates) is useful here. The seams that are good extraction candidates are the ones where the team can identify a clear owner, a clear data boundary, and a small surface area of cross-domain calls. The seams that aren't good candidates are those where cross-domain calls are dense and data ownership is genuinely shared.
Strangler Fig Pattern
Martin Fowler's strangler fig pattern is the canonical migration approach: introduce a facade in front of the monolith that gradually routes traffic to the new service, keeping the old code path in place until the new service is proven. The metaphor is that the new service grows around the old one and eventually replaces it, much like a strangler fig growing around a host tree. The pattern works because it lets the team migrate incrementally without a Big Bang deployment.
Database Decomposition
This is the hardest part of any real migration. Splitting a database shared by several monolithic modules into per-service datastores requires the team to identify which service owns which data, how to handle genuinely shared data, and how to handle cross-service queries that used to be SQL joins. Most failed migrations failed here. Plan accordingly, or don't start.
Observability and Network Resilience Prerequisites
Microservices require an observability investment that the monolith never needed. Distributed tracing isn't optional; it's how you debug a single user request across services. Retries, circuit breakers, idempotency, and graceful degradation are mandatory at the service boundary. If the team doesn't have these primitives, the migration will expose every weakness in the operational story.
Migration Anti-Patterns
A few well-known failure modes worth naming upfront:
- Big Bang migrations. Try to flip from a monolith to microservices in a single release. Predictably fails most of the time, especially with large-scale operations.
- Premature decomposition. Split into services based on what might be useful eventually rather than what is actually owned by separate teams now.
- Distributed monolith. Split into services that still share a database and still need to deploy together. Worst of both worlds.
- Service-per-noun decomposition. Every entity in the domain becomes a microservice. Produces hundreds of trivial services that all need to talk to each other.
The broader treatment of how to sequence this work within a larger program is in our application modernization roadmap post, which covers how the migration fits within the modernization cluster.
Common Monolith-to-Microservices Anti-Patterns
The patterns above show up at the architectural level. A few more show up at the operational level.
The Distributed Monolith
The single most common failure mode. The team splits the monolith into services that still need to be deployed together, still share a database, and still couple at the data layer. The result is all the operational complexity of microservices with none of the architectural benefits. Distributed monoliths are also harder to back out of than the original monolith because the team has paid the cost of the split without earning the benefit.
Service per Ticket
Each new feature gets a new microservice. After two years, the team is running 87 services for a 12-person engineering team. Operationally, this is unsupportable. The fix is service ownership at the team level, not the ticket level.
Database-as-API
Two services share a database, and one reads tables, the other writes. This is "microservices" in name only; the coupling at the data layer is as tight as if they were a single application, and the architecture is now harder to reason about. Shared databases are usually a sign that the service boundary is incomplete. They may be acceptable as a temporary step during a migration; they shouldn't be the steady-state architecture for independently deployable services.
100 Microservices for a 5-Person Team
The pattern that has produced the most "we went back to monolith" stories. The operational cost of running each service exceeds the value the service produces; the team's cognitive load is consumed by infrastructure work that doesn't ship features. The fix is consolidation. The cost of consolidating is real, but it's almost always less than the cost of continuing.
The broader connection to technical debt is direct: a distributed monolith is technical debt compounded across a network. The cost compounds faster than in-process debt because every refactor crosses a service boundary.
The Architecture-Decision Discipline This Requires
Every step in a monolith-to-microservices migration is an architecture decision. Which service to extract first, which database split to do, which communication pattern to standardize on, what observability investment to make, and which downstream impact is acceptable? Most teams treat these as execution decisions, but they aren't. They are the decisions on which the migration is built.
In practice, the decisions get made by whichever engineer is closest to the extraction at the moment of execution. The decision lives in their head or in a Slack thread. Three years into the migration, the team has executed dozens of decisions whose context, alternatives, and consequences are lost. When something breaks (and it will), the team can't reconstruct why the original choice was made or what it was meant to trade off.
This is where Catio helps to close the gap. Our Architecture IDE treats every migration decision as a first-class artifact tied to the live state of the system, so the team can revisit decisions when the context changes (and migrations always change context), see how decisions interact across the portfolio, and detect when the running system has drifted from what was committed to. The migration mechanics still apply; the decision layer is what keeps the program reviewable. We've written separately about architecture decision records and how the static-document model is evolving as systems get more complex; a long-running migration is the case that stresses that model hardest.
A migration without a place to land its architectural decisions is a program waiting to discover, in year two, that nobody remembers why the team chose Kafka over Kinesis, why the auth strategy was federated instead of centralized, or whether the database decomposition decision still holds for the team that owns it now. Connecting the migration to its decision substrate is what keeps that from happening.
Closing the Loop
Monolith to microservices isn't a fight to win. It's a decision to make. The discipline that holds up is to evaluate the case explicitly, name the trade-offs, write them down, and revisit them as the team learns what the architecture actually needs.
If your team is in the middle of this decision (or worse, in the middle of executing it without having made the decision explicitly), see how Catio treats the migration as a system of architecture decisions tied to live state, so the work stays connected to the choices the team committed to rather than drifting away from them.
Frequently Asked Questions
What is monolith to microservices?
Going from monolith to microservices means breaking a single deployable application into a set of independently deployable services, each owned by a team, communicating over the network, with separate data ownership. It used to be the default modernization path; in 2026, the recommendation is conditional on team size, scaling profile, and operational maturity.
How would you split a monolith into microservices?
By identifying domain boundaries first, using the strangler fig pattern to extract one service at a time behind a facade, decomposing the database alongside each service extraction, and investing in the observability and network-resilience primitives the new architecture requires. Big Bang migrations don't work; incremental ones do.
Why did Netflix move from a monolithic app to microservices?
Netflix's migration in the early 2010s was driven by team size and independent scaling needs that genuinely fit the microservices pattern: many product teams, each owning a deployment cadence, with subsystems that had very different scaling profiles. The lesson most companies took ("we should also do microservices") was the wrong one for most of them; the lesson that applied was "evaluate against the same criteria Netflix did."
Is the modular monolith just a microservice in disguise?
No. A modular monolith is a single deployable with strong internal module boundaries. A microservice is an independently deployable unit with its own data ownership. The modular monolith trades independent deployment for operational simplicity; the microservice trades operational simplicity for independent deployment. Different commitments, different trade-offs.
When should you not migrate to microservices?
When the team is below the size threshold (~50 engineers), when the scaling needs aren't differential across the system, when the isolation requirements can be met in code, when the operational team can't support a distributed system, or when the cost of running each service would exceed the value it produces. Most teams asking the question fall into at least one of these.



