Monolith vs Microservices: How to Actually Decide
Microservices solve an org-scale problem, not a code problem. Here is how to actually decide between a monolith and microservices, and why most startups should start with the monolith.
Key takeaways
- A monolith deploys as a single unit and calls functions in-process, while microservices split the system into independently deployable services that talk over the network, so the core tradeoff is deploy simplicity versus independent scaling and independent deployment.
- Microservices solve an organizational scaling problem, letting many teams deploy independently without stepping on each other, not a code-quality or performance problem, which is why a small team rarely gets a net benefit from them.
- The distributed monolith is the worst outcome: services split across the network that still have to deploy together because they are tightly coupled, so you pay the operational cost of microservices and get none of the independence.
- Martin Fowler argues you should almost always build a monolith first and only extract services once the monolith gets big enough to feel painful, because you cannot draw good service boundaries before you understand the domain.
- Conway's Law says a system's architecture tends to mirror the communication structure of the organization that builds it, so microservices work best when the team is already split into small, autonomous groups that own their services end to end.
Somewhere along the way, microservices stopped being an architecture choice and turned into a status symbol. A team of six would spin up fourteen services, a service mesh, and a stack of dashboards, then spend the next year debugging why a single user action now touched nine network hops. Meanwhile the actual product barely moved. I have watched this happen more than once, and the root cause is almost always the same: someone picked the architecture before they understood the problem it exists to solve.
Here is the honest framing of monolith vs microservices. A monolith is one deployable app where everything runs in the same process. Microservices break that app into many small services that deploy on their own and talk over the network. The thing nobody says out loud is that microservices are not a better way to write code. They are a way to let a lot of teams ship without tripping over each other. That is an org problem, not a code problem, and if you do not have that problem yet, you are buying the cost without the benefit.
Summary
What each one actually is
A monolith is a single codebase that builds into a single artifact and runs as a single process. Your web layer, your business logic, your data access, all of it lives together and calls each other directly. When module A needs something from module B, it is a function call. Fast, in-memory, transactional, easy to reason about. You deploy the whole thing at once.[1]
Microservices take that same functionality and slice it into independent services, each with its own codebase, its own deployment, and usually its own database. When service A needs something from service B, it is now a network call over HTTP or gRPC.[2] That one change, function call to network call, is the entire story. Everything good and everything bad about microservices falls out of it. You gain the ability to deploy and scale B without touching A. You inherit latency, partial failure, retries, timeouts, and the fact that B might just not answer.
The tradeoff nobody frames honestly
People sell microservices on scalability, as if a monolith cannot scale. That is mostly wrong. A monolith scales fine horizontally: you run more copies behind a load balancer. What a monolith cannot do is scale one piece independently. If your image-processing code is the bottleneck, in a monolith you have to scale the whole app to get more of it. In microservices you scale just the image service. That is a genuine win, but only if you actually have a component whose scaling profile is wildly different from the rest.
The real axis is deploy simplicity versus independent deployment. A monolith is one deploy, one rollback, one place to look when it breaks. Microservices give every team its own release cadence, which is enormously valuable when you have twelve teams and paralyzing when you have one. Google Cloud and AWS both frame the choice this way in their architecture guidance: microservices trade operational and cognitive simplicity for organizational and scaling flexibility.[3][4]
| Dimension | Monolith | Microservices |
|---|---|---|
| Deployment | One unit, one release | Independent per service |
| Scaling | Whole app together | Per component |
| Calls between parts | In-process function calls | Network calls, can fail |
| Data consistency | Single DB, real transactions | Per-service DB, eventual consistency |
| Best fit | Small team, one codebase | Many autonomous teams |
Data consistency is where it hurts most
The part that surprises people is data. In a monolith you have one database, and you get real transactions. Debit one account, credit another, either both happen or neither does. The database guarantees it. It is boring and it is correct.
Split those into two services with two databases and that guarantee is gone. You cannot wrap a transaction across a network boundary. Now you are reaching for patterns like sagas, outbox tables, idempotency keys, and eventual consistency, and you are writing code to handle the case where the debit succeeds and the credit fails. This is not a rare edge. It is the normal state of a distributed system, and it is a huge amount of work that a monolith simply hands you for free.
Why this matters
This is also why the boundary between services matters so much, and it connects to a broader question about how your APIs talk to each other. If you are going down the services path, the shape of those calls, whether they are REST, GraphQL, or gRPC, becomes a first-order decision, which I dig into in REST vs GraphQL vs gRPC.
The distributed monolith: the worst outcome
Here is the failure mode I have seen sink more teams than any other. You split your monolith into services, but the services are still tightly coupled. Service A cannot deploy without service B being on a matching version. They share a database. A change to one forces a change to three others. You now have to deploy them together, in lockstep, coordinating releases across the network.
That is a distributed monolith, and it is strictly worse than either pure option. You pay the full microservices tax, network latency, partial failures, harder debugging, more infrastructure, but you get none of the independence that was supposed to justify it. You took a thing that was simple and coupled, and made it complicated and still coupled.
“A distributed monolith gives you all the operational cost of microservices and none of the independence. It is the tax with no service.”
Takeaway
If your services have to deploy together, they are not microservices, they are a monolith that someone scattered across a network. The single clearest sign you split too early or along the wrong lines is that you can never release just one service on its own.
Conway's Law is the whole game
Conway's Law says that any organization designing a system will produce a design whose structure mirrors the organization's own communication structure.[5] Coined by Melvin Conway in 1967, it started as an observation and has quietly become the most useful lens for this entire decision.
Think about what that means. If you have one team, your software wants to be one thing. Forcing it into fifteen services that one team has to keep coordinated fights the natural grain, and you feel it as constant cross-service friction. But if you have fifteen small teams that each own a slice of the product end to end, a monolith fights that grain instead, because now everyone is contending over one shared release. Microservices work when the org is already shaped like microservices. The architecture is downstream of the org chart, not the other way around.
Context
Why most startups should start with a monolith
Martin Fowler, who did as much as anyone to popularize the term microservices, is blunt about this: build a monolith first.[6] His argument is not sentimental, it is practical. Microservices carry a premium, a baseline cost in operational complexity you pay before you get any benefit, and that premium only pays off past a certain size and complexity.[7]
The deeper reason is that you cannot draw good service boundaries before you understand the domain, and early on you do not understand the domain. You think you do. You are wrong, and that is fine, that is what building the product teaches you. If you commit to service boundaries in month two, you are hard-coding your least-informed guess into the most expensive-to-change part of the system. A monolith lets those boundaries stay soft and cheap to move until you actually know where they go. Then you extract services along the seams that experience revealed, not the ones you imagined.
None of this means write a mess. A monolith should still be modular inside, with clean internal boundaries, so that if you do need to extract a service later, the seam is already there. The relationship between how you split your code and how you split your repositories is its own decision, one I get into in monorepo vs polyrepo. And once you are running many services, the deployment substrate matters, which is where the Docker vs virtual machines tradeoff starts to bite.
What I'd do
The way I think about it, microservices are an answer to a question most teams have not been asked yet. The question is: how do we let a large number of teams ship independently without a single release becoming a coordination nightmare? If that is your problem, microservices are a great answer, and you should pay the tax gladly because the alternative is worse. If that is not your problem, you are cosplaying as a company ten times your size and paying for the privilege.
So my default is simple. Start with a modular monolith. One codebase, one database, clean internal boundaries, one deploy. Ship the product, learn the domain, grow the team. When you feel real pain, a component that genuinely needs to scale alone, or two teams that keep blocking each other on a shared release, extract exactly that service and no more. Let the pain draw the boundary. Do not draw it in advance and then go looking for pain to justify it. The best architecture is the one your team and your problem actually need today, not the one that looks impressive in a system design interview.
Sources and further reading
- 1.PrimaryWikipedia, "Monolithic application". A monolithic application is self-contained and independent, with its components composed into a single deployable program.
- 2.PrimaryWikipedia, "Microservices". Microservices structure an application as a collection of independently deployable services that communicate over a network.
- 3.PrimaryGoogle Cloud, "Introduction to microservices architecture". Independent deployment and scaling of services traded against distributed-system complexity and data consistency challenges.
- 4.PrimaryAmazon Web Services, "What are Microservices?". Microservices let teams own and deploy services independently, enabling organizational and scaling flexibility.
- 5.PrimaryWikipedia, "Conway's law". Organizations design systems that mirror their own communication structure; coined by Melvin Conway in 1967.
- 6.ReportingMartin Fowler, "MonolithFirst". Build a monolith first and extract microservices once boundaries are understood; premature splitting locks in the wrong ones.
- 7.ReportingMartin Fowler, "MicroservicePremium". Microservices carry a baseline complexity cost that only pays off past a certain level of system and team scale.
Frequently asked questions
- What is the difference between a monolith and microservices?
- A monolith is a single deployable application where all the code runs in one process and modules call each other as function calls, while microservices split that same functionality into many small services that each deploy independently and talk to each other over the network. The monolith is simpler to build, test, and deploy because it is one thing. Microservices let different parts scale and ship on their own schedules, at the cost of network calls, distributed data, and a lot more operational machinery.
- Should a startup use microservices?
- No, most startups should start with a monolith and only move to microservices once they hit a real team-coordination or scaling problem. Early on you do not yet understand your own domain well enough to draw good service boundaries, and splitting too early locks in the wrong ones. A well-structured monolith gets you to product-market fit faster with far less operational overhead, and you can always extract services later when the pain is concrete.
- What is a distributed monolith?
- A distributed monolith is a system that has been split into separate services over the network but is still so tightly coupled that the services have to be deployed together, which is the worst of both worlds. You pay the full operational tax of microservices, network latency, distributed failures, harder debugging, but you get none of the independence that was the point. It usually happens when a team splits a monolith along the wrong boundaries or shares a database across every service.
- What problem do microservices actually solve?
- Microservices primarily solve an organizational scaling problem: they let many teams work and deploy independently without coordinating a single shared release. The technical benefits, independent scaling of hot components and fault isolation, are real but secondary. If you have one small team, you do not have the coordination problem microservices exist to solve, so you mostly inherit the costs without the payoff.
- How does Conway's Law relate to microservices?
- Conway's Law states that organizations design systems that mirror their own communication structure, so the shape of your software ends up matching the shape of your org chart. This is why microservices tend to succeed when a company is already organized into small, autonomous teams that each own a service end to end, and tend to fail when one big team tries to run many services. The architecture and the org structure have to match.
Written by
Tech Talk News Editorial
Computer engineering background. Writes about software, AI, markets, and real estate, and the places where the three meet.
More about the author