Monolith vs Microservices: Making the Call
The most over-answered question in system design. When splitting genuinely helps, why most microservice migrations fail, and how to defend keeping the monolith.
Covers: Service boundaries, Conway's law, the distributed monolith, modular monoliths, migration strategy, when to split
Candidates reach for microservices because they sound senior. They are frequently the wrong answer, and an interviewer who has actually run a distributed system will probe hard. The strongest response is almost always “a modular monolith, and here is the specific signal that would make me split”.
30-second answer
Split when teams block each other: when a deploy requires coordinating several teams, when one component needs a radically different scaling or reliability profile, or when a subsystem genuinely needs a different technology stack. Do not split because the codebase is large, because the architecture diagram would look more modern, or before you know where the boundaries are. Below roughly 20–30 engineers, a modular monolith with enforced internal boundaries gives you most of the benefit and almost none of the cost.
| Signal | Split? | Why |
|---|---|---|
| Two teams cannot deploy without coordinating | Yes | The core problem microservices actually solve |
| One component needs 100× the instances of the rest | Yes | Independent scaling is a genuine technical win |
| One subsystem needs a different runtime (ML in Python, rest in Go) | Yes | Technology isolation is legitimate |
| One component must not take the others down | Yes | Fault isolation, if the boundary is real |
| The codebase is big | No | Modularise inside the monolith first |
| We want to use Kubernetes properly | No | Not a business reason |
| Onboarding is slow | No | Documentation and module boundaries are cheaper |
| Boundaries are not yet clear | Definitely not | You will get them wrong and freeze them in network calls |
What splitting actually costs
- Availability multiplies down. Six services at 99.9% on the critical path give 99.4% - around 4 hours of downtime a month, up from 43 minutes.
- Transactions become sagas. An ACID transaction across two tables becomes a multi-step compensating workflow across two services.
- Debugging needs new tools. A stack trace becomes a distributed trace, and you must build that before you need it, not during the first incident.
- Latency accumulates. Every hop is a serialisation, a network round trip and a deserialisation where you previously had a function call.
- Operational surface multiplies. Each service needs deploys, dashboards, alerts, on-call, dependency updates and a security review.
Finding the boundary
Follow the data, not the nouns
A good service owns its data exclusively. If two candidate services need to write the same table, the boundary is in the wrong place - you have found a single domain, not two.Follow team ownership (Conway's law)
Systems mirror the communication structures of the organisations that build them. Boundaries that cut across a single team create constant cross-team friction; boundaries that match team ownership work.Follow the rate of change
Code that changes together should live together. If two modules are always modified in the same pull request, splitting them creates lock-step deploys - the worst of both worlds.Follow the failure domain
If the payment path must survive the recommendation engine falling over, that is a real boundary worth paying for.
Migrating, if you must
The strangler fig pattern: put a facade in front of the monolith, extract one capability at a time behind it, route a small percentage of traffic to the new service, verify by comparing results, then move the rest and delete the old code. Start with a leaf capability that owns its own data and has few callers - notifications, PDF generation, search indexing. Never start with the core domain, and never attempt a big-bang rewrite.
Say these points
- Microservices solve an organisational problem: independent deployment by independent teams.
- Availability multiplies down across critical-path services.
- A distributed monolith has all the cost and none of the benefit - test with 'can it deploy alone?'.
- Modular monolith first; boundaries are cheap to move before they are network calls.
- Migrate with the strangler fig, starting from a leaf capability that owns its data.
Avoid these mistakes
- Splitting before the boundaries are understood.
- Multiple services sharing one database.
- Ignoring the availability arithmetic.
- Big-bang rewrites.
- Justifying the split with technology rather than with team or scaling constraints.
Expect these follow-ups
- Two services need the same data. How do you resolve that without a shared database?
- How do you enforce module boundaries inside a monolith so they do not erode?
- When would you merge two microservices back together?
Showing 1 of 1 questions for monolith-vs-microservices.
Check your understanding
3 questions · no sign-up, nothing stored