"As you think about legacy code, it's helpful to remember two things. First, it's been running your business this long and got you to where you are today. That is something to celebrate. Second, today's modern technology is just tomorrow's legacy."
TL;DR: 42% of companies that adopted microservices are consolidating back. The problem isn't microservices — it's skipping the middle stage. The Architecture Readiness Model has 3 stages: monolith (ship fast, under 10 engineers), modular monolith (enforce domain boundaries, post-PMF), selective microservices (extract only when you have a specific, proven scaling constraint and 15+ engineers with mature DevOps). Most teams aren't in Stage 3 yet.
Somewhere along the way, "monolith" became a dirty word. Engineers use it the way they might say "technical debt" or "legacy codebase" — a polite word for something embarrassing, something you tolerate until you can afford to fix it.
And "microservices" became the opposite: modern, scalable, what serious companies do.
So companies migrated. Some spent years on it. Some spent millions. And now, according to the CNCF 2025 Annual Survey, 42% of those companies are consolidating their microservices back into larger, more unified systems. Gartner puts it bluntly: 60% of teams regret the decision for small-to-medium applications.
The binary framing — monolith bad, microservices good — was always wrong. The real question isn't which architecture is better. The question is whether your company has earned the right to split yet.
Most haven't. And most don't know it.
What microservices actually cost in 2026
Before getting to the framework, let's be concrete about the price of a premature migration.
Microservices infrastructure runs 3.75 to 6 times more expensive than an equivalent monolith setup. At enterprise scale, that translates to roughly $15,000 per month for a monolith versus $40,000–$65,000 for microservices, when you factor in infrastructure, platform teams, and coordination overhead.
Debugging takes 35% longer in microservices architectures than in modular monoliths (DZone, 2024). Service mesh adoption, the tooling that makes microservices manageable, has collapsed from 18% of teams in Q3 2023 to just 8% in Q3 2025. Teams are quietly walking away.
73% of organizations report struggling with microservices complexity (Stack Overflow). In 2026, the "microservices tax" — the overhead of managing a distributed system — can represent up to 40% of your maintenance budget.
The Amazon Prime Video team migrated their video quality analysis service back from distributed microservices to a single-process monolith and cut infrastructure costs by 90%. This wasn't a failure story. It was a rational engineering decision.
Shopify runs one of the most demanding retail systems in the world on a monolith: 2.8 million lines of Ruby, handling 30 terabytes per minute and 32 million requests per minute during Black Friday peaks.
Neither Amazon nor Shopify "failed at microservices." They made the right architectural choice for their actual situation.

Three architectures, three stages — the model most teams skip
Martin Fowler wrote in 2015: "Almost all the successful microservice stories have started with a monolith that got too big and was broken up."
He was right. But most teams read that as a two-step process: start with monolith, move to microservices. There's a stage in between that almost nobody talks about — and skipping it is where the regret comes from.
Here's the Architecture Readiness Model we use when helping clients think through this decision.

Stage 1: Monolith. One codebase, one deployment unit. Every module lives together. This is fast to build, cheap to run, and easy to debug. For early-stage products, for MVPs, for teams under 10 engineers — this is the right architecture. If you're building a SaaS application from scratch, start here. The cost of distributing a system you don't fully understand yet is enormous.
Stage 2: Modular monolith. Still one deployment unit, but with strict internal module boundaries. Each domain owns its own code, its own data models, and its own interfaces. Modules communicate through defined APIs, not by reaching into each other's internals. This is where Shopify has been for years. It scales surprisingly far. It's much easier to reason about than a distributed system, and it sets you up to extract services later — cleanly — when you actually need to.
Stage 3: Selective microservices. You extract services — not all of them, specific ones — that have proven, independent scaling needs. Not because microservices are modern. Because a specific service needs to scale at a different rate than the rest of your system, and that need is measurable, not theoretical.
Most companies jump straight from Stage 1 to Stage 3. They skip the modular monolith entirely. Then they spend 40% of their budget managing the distributed system they created, and wonder why development got slower.
The modular monolith isn't a compromise. It's the stage that earns you the right to go further.
How to know which stage you're actually in
Sam Newman, whose book on microservice migration patterns is the closest thing this field has to a standard reference, recommends three questions before adopting microservices:
- What are you hoping to achieve?
- Have you considered alternatives?
- How will you know if the transition is working?
Those questions are useful. But before you get there, here's a more concrete readiness assessment.
DevOps maturity. Microservices require mature deployment infrastructure: scripted deployments, infrastructure as code, CI/CD pipelines, automated testing, code review standards. Without these, you can't manage one service reliably, let alone dozens. If your team deploys manually, or doesn't have standard processes for testing and rollback, microservices will make everything harder. A CI/CD pipeline isn't a nice-to-have before a migration — it's a prerequisite.
Team size. Below 15 engineers, the coordination overhead of microservices typically exceeds the benefit. Above 15–20, teams start to need autonomy over their domain — and microservices start to enable that autonomy rather than fight it. The two-pizza rule Jeff Bezos described ("teams no larger than can be fed by two pizzas") isn't just a culture principle — it describes the minimum team unit capable of owning and maintaining a service end-to-end.
Domain boundaries. Can your codebase actually be separated by business domain? In many systems, every entity depends on every other entity. If your architecture doesn't have clear, enforceable boundaries today, microservices won't create them — it'll just spread the dependency mess across network calls.
A specific scaling need. The trigger for extracting a service should be a specific, measured constraint. Not "we think this will need to scale someday." A real ceiling: a service that handles 10x the traffic of everything else, a module that needs independent deployment cycles, a domain with genuinely different availability requirements.
Organisational structure. Do you have teams that can design, build, deploy, and maintain a service without external approvals? Microservices work when the architecture matches the org chart. If your team structure doesn't support autonomous ownership, the architecture won't either.
If you read through that list and found gaps, you're not ready for Stage 3. The right move is Stage 2 — invest in module boundaries, enforce them with code, and wait until a real scaling signal emerges.
When migration is the right call
The point isn't that migration is wrong. For some systems, at the right moment, it's exactly right.
One of our clients, Lake, ran a vacation rental platform on a monolithic back-end. The architecture worked for years — until demand grew faster than the system could handle. The monolith had a hard ceiling on the number of vacation properties it could connect. With roughly 500 properties on the platform and demand pushing far beyond that, staying on the existing architecture meant capping growth.
That's a specific, measurable problem. A real ceiling, not a hypothetical one.
We rebuilt Lake's back-end architecture in 3 months. The result: 80x growth in connected properties — from 500 to 40,000 — and a 210% spike in website activity. Lake had earned the right to split, and the results reflected that.
Netflix's migration tells a similar story, though at a different scale and timeline. Their monolith was causing outages, creating service interdependencies that no team could untangle, and failing to scale with their customer base. The migration took 7 full years. It required moving to AWS, switching to NoSQL databases, and rebuilding core services one by one.

Netflix Microservices Infrastructure
What those migrations share: both started with a real constraint, not a preference. The architecture was holding the business back in a measurable way. That's the signal.
Step-by-step: how to migrate without breaking your product
If you've worked through the readiness checklist and the answer is yes — a specific service genuinely needs to come out of the monolith — here's how to approach it without causing damage.

Set concrete goals first. What outcome are you after? Increased uptime? Independent scaling for a specific service? Faster deployment cycles for one team? The outcome determines the scope. Don't start a migration with "modernise the architecture" as the goal — that's a description of activity, not a result.
Define domain boundaries before writing a line of new code. Correct service boundaries are the foundation of a healthy microservices architecture. Wrong boundaries mean a change to one service cascades into changes in five others, which turns independent deployments into an integration coordination nightmare.
Istio is a good cautionary example here. They migrated to microservices, then reversed course and moved the control plane back to a monolith after realising that all their control plane services were deployed together, shared the same administrative domain, and provided no real benefit from being separate. The split created complexity without enabling independence. Make sure the domain you're extracting is genuinely independent before you extract it.
Identify the highest-value services to move first. Some functionality provides clear value as a separate service. Other functionality is deeply entangled with the rest of the system. Start with the isolated, high-value pieces — email, notifications, authentication, payment processing. Leave the entangled core for later or leave it in place.
Give each service its own data store. One data repository per service. This is non-negotiable. Shared databases create the same coupling you were trying to escape. Individual stores can get out of sync — invest in master data management tooling and keep a redundant copy in the monolith during the transition.
Don't rewrite the extracted microservice. Keep the code of the migrated service clean and separate. When new functionality is needed, create a new service rather than modifying a running one. This lets you deploy and test independently without risking the existing service.
Separate build, separate container. Run a separate build process for each microservice. Deploy in containers — Docker is the standard. This is what makes independent deployment actually work.
Manage the migration without stopping the system. Users need access during the process. The Strangler Fig pattern — gradually replacing parts of the monolith while keeping it running — is the most reliable approach. Extract one service, run both in parallel, validate, then decommission the monolith version of that piece.
For examples of companies that have done this well, see successful practices from Netflix, Wix, Best Buy, and others.
The decision
Here's how to think about it clearly.
Pre-product-market-fit, or under 10 engineers: stay on the monolith. Ship fast. Validate. Don't pay the microservices tax on a product that might pivot three times before it finds its market.
Post-PMF with a growing codebase and growing team: move to a modular monolith. Draw domain boundaries. Enforce them with internal APIs. This will serve you well past the point where most teams jump to microservices — and it will make the eventual extraction much cleaner when it comes.
A specific service has a proven, independent scaling need, your DevOps practices are mature, and your team is 15 or more engineers: you've earned the right to extract. Do it surgically. One service at a time. With a real outcome in mind.
The architecture that works is the one that fits where you actually are, not where you plan to be in three years.
At Brocoders, we've helped teams at all three stages: building SaaS applications from scratch on well-structured monoliths, modernising legacy applications that had hit real ceilings, and designing extraction strategies for teams that had genuinely outgrown their architecture.
If you're unsure which stage you're in, we're happy to look at your architecture and give you a straight answer.
FAQ
What is the difference between a monolith and microservices?
A monolith is a single deployment unit where all application logic runs together. A microservices architecture breaks the application into independent services, each responsible for one business domain, deployed and scaled separately. In a monolith, all components share the same codebase and database. In microservices, each service owns its own code, its own data store, and communicates with other services over a network.
When should you migrate from monolith to microservices?
The right trigger for migration is a specific, measurable constraint your current architecture can't solve. A service that needs to scale at 10x the rate of everything else. Independent deployment cycles that your current structure prevents. Organisational scale — 15+ engineers — where team autonomy starts to require architectural autonomy. Migrating because microservices are "more modern" or because competitors use them isn't enough justification.
What is a modular monolith and how is it different from microservices?
A modular monolith enforces strict internal boundaries between domains while remaining a single deployment unit. Each module owns its own code and communicates with other modules through defined interfaces, but everything deploys together. Microservices deploy independently. The modular monolith offers most of the structural benefits of microservices — clear domain ownership, enforced boundaries, easier reasoning about scope — without the distributed systems overhead.
How long does it take to migrate from monolith to microservices?
It depends heavily on the scope. Extracting a single, isolated service from a well-structured codebase can take weeks. Rebuilding a full back-end architecture with real scaling constraints — like the Lake project we delivered in 3 months — is measured in months when approached with clear goals and a focused team. Netflix's complete migration took 7 years. Scope your extraction by outcome, not by a desire to move everything.
Can a monolith handle serious scale?
Yes. Shopify runs a 2.8-million-line Ruby monolith that handles 30 terabytes per minute and 32 million requests per minute during peak traffic. Stack Overflow served billions of requests per month on a small cluster of servers running a monolithic .NET application. Scale depends on good architecture, caching strategy, and database design — not on whether services are deployed separately.
What team size justifies microservices?
Most engineering teams cite 15 to 20 engineers as the threshold where microservices overhead starts to pay off. Below that, the coordination cost of managing distributed services exceeds the autonomy benefit. The right question is whether your team can own a service end-to-end — design, build, deploy, and maintain — without requiring approvals or coordination from other teams. If the answer is no, the organisational structure isn't ready, regardless of team size.
What is the strangler fig pattern?
The strangler fig pattern is a migration strategy where you gradually replace parts of a monolith by building new services alongside it rather than replacing the whole system at once. New functionality goes into the microservice. The monolith version of that functionality continues running until the new service is validated. Then the monolith piece is decommissioned. This approach keeps the system running throughout the migration and reduces risk significantly compared to a full rewrite.