Microservices vs Monolith — When to Split
Fast recall
Quick revision
Core answer
Whether you understand microservices are a trade-off, not a universal upgrade
Saying 'microservices are always better' without discussing complexity
Mention the Strangler Fig pattern for migration and the two-pizza team rule
Interview-ready guide
Interview answer
Microservices give you independent deployability and independent scalability — but at the cost of in-process calls, shared-database transactions, and simple single-service debugging. The decision should not be about the pattern's popularity but about whether you have a concrete problem that microservices solve better than a well-structured monolith.
When the split makes sense:
- Deploy contention is the clearest signal — when teams routinely block each other's releases and merge-to-production takes three days due to coordination overhead, that organizational friction is exactly what microservices fix
- Scaling skew is the second signal — when one module needs 10× the compute of everything else, you're paying to scale the whole monolith to support one hot component
- Domain boundaries should be stable for at least six months before extracting — use Domain-Driven Design to identify bounded contexts first
The distributed monolith trap:
- Splitting code without splitting data or decoupling call paths gives you network latency plus tight coupling — no real independence gained
- If Service A can't deploy without coordinating with Service B, you haven't actually split; you've just added network hops to your monolith
- Services that call each other synchronously for every operation recreate the coordination problem in a more expensive form
How to migrate safely:
- Always use the Strangler Fig pattern — route traffic at the gateway incrementally to new services while the monolith handles everything else
- Start with low-risk, well-bounded domains like notifications or user profiles, not payments or checkout
- Maintain a rollback path at every step — gateway routing is a one-line revert, and the monolith's code stays intact for at least one release cycle
I recommend the monolith-first default: only split when you can name the concrete problem — deploy contention, scaling skew, or team ownership — that microservices solve better than a modular monolith.
Microservices vs Monolith — When to Split
Direct Answer
Split when independent scalability, team autonomy, or deployment isolation justify the added operational complexity. A monolith is the right default for most teams.
Code Example
Treat the split decision as a structured audit, not a gut call. A minimal checklist encoded as Java makes the criteria explicit and reviewable in PRs.
public enum SplitDecision { STAY_MONOLITH, MODULAR_MONOLITH, SPLIT }
public record TeamShape(
int engineers, // total headcount
int independentSquads, // squads with separate release cadence
boolean ciCdMature, // can we actually run 10 pipelines?
boolean observabilityReady // traces, metrics, on-call
) {}
public record ProductShape(
int boundedContexts, // stable >= 6 months
boolean sloDifferentiation, // e.g., checkout needs 99.99, analytics 99.5
boolean scalingSkew, // one module needs 10x compute of others
int deployConflictsPerMonth // teams blocking each other's deploys
) {}
public static SplitDecision decide(TeamShape team, ProductShape product) {
// Hard floor: no infra maturity = no microservices
if (!team.ciCdMature() || !team.observabilityReady()) {
return SplitDecision.STAY_MONOLITH;
}
// Below the team threshold, modular monolith captures 80% of the value
if (team.engineers() < 15 || team.independentSquads() < 3) {
return SplitDecision.MODULAR_MONOLITH;
}
// Pain signals that justify the operational tax
boolean realPain =
product.deployConflictsPerMonth() >= 4
|| product.scalingSkew()
|| product.sloDifferentiation();
boolean boundariesStable = product.boundedContexts() >= 3;
return (realPain && boundariesStable)
? SplitDecision.SPLIT
: SplitDecision.MODULAR_MONOLITH;
}
Checklist as a team-size vs service-count matrix — the operational tax budget:
| Engineers | Squads | Recommendation | Why |
|---|---|---|---|
| < 10 | 1 | Monolith | coordination is the whole product |
| 10–15 | 1–2 | Modular monolith | boundaries via modules + ArchUnit |
| 15–30 | 2–3 | Modular monolith OR first extraction | extract only if concrete pain |
| 30–80 | 3–6 | Microservices, 5–8 services | one bounded context per squad |
| 80+ | 6+ | Microservices, 10+ services | Conway's law takes over anyway |
Operational cost budget per service — 3 to 5 engineer-hours per week (CI/CD, monitoring, alerts, on-call shared). Multiply by N services before committing: a 10-service fleet implies 30–50 weekly hours just on ops, before any feature work. If that exceeds 25% of your team's capacity, you're understaffed for the architecture.
Common Mistakes & Pitfalls
Saying 'microservices are always better' without discussing complexity
Check your understanding
Answer these without looking back at the article.
- How do you identify bounded contexts in a domain?
- What is the Strangler Fig migration pattern?
- How do you handle shared databases when splitting a monolith?
Related interview prep categories
2Want a guided curriculum order?
These modules are also sequenced in our flagship backend interview track — open it when you prefer an ordered path instead of browsing by topic.