Monolith vs Microservices vs Modular Monolith
Fast recall
Quick revision
Core answer
Trade-offs of each (not just 'microservices = good'), why modular monolith is often the right starting point, and the criteria for extracting a service.
Treating microservices as universally better, or thinking 'microservices = small'. Size isn't the point — deployment independence is.
Discuss the operational tax of microservices (CI/CD, observability, on-call, data consistency), and walk through the modular monolith → selective extraction migration path.
Interview-ready guide
Interview answer
The three models
Monolith: single deployable, one codebase, one DB. Internal calls are method calls — fast, transactional, type-checked. All teams release together.
Microservices: many small services, each independently deployable, each with its own DB. Communication over network — REST, gRPC, async events. Each team owns end-to-end. Failures partial; consistency eventual.
Modular monolith: single deployable but internally split into well-bounded modules. Each owns its data, exposes a contract. Deployed together but designed as if extractable. One pipeline, one DB instance with logical separation.
Trade-off matrix highlights
Deployable units: 1 / 1 / N Database: 1 shared / 1 logically separated / N per service Internal calls: method / module API / network Transactions: local ACID / local ACID / distributed via saga Team autonomy: low / medium / high Independent scaling: no / no / yes Failure isolation: no / no / yes Operational complexity: low / low / high Observability: logs + APM / logs + APM / distributed tracing required
When each wins
Monolith: 1-10 devs, early-stage product, churning requirements, strict local-ACID needs.
Modular monolith: 10-50 team, want microservices discipline without operational tax, future-proofing for selective extraction, DDD bounded contexts clear but in-process performance matters.
Microservices: 50+ across multiple teams needing independent release cadences, wildly different scaling needs (search vs checkout), different runtimes (Python ML + Java payments), high-availability requires failure isolation, independent data store requirements.
The hidden cost of microservices
- Operations: N pipelines, service discovery, distributed tracing required, centralized logs, service mesh
- Data: no cross-service joins, sagas + compensations, event-driven for consistency, coordinated schema evolution
- Networking: latency budget consumed by hops, retries/timeouts/circuit breakers everywhere
- Team: 24/7 on-call per service, steeper hiring bar, cross-team coordination
Rule of thumb: if 5 small teams could deliver the same product, microservices probably aren't worth it yet.
Modular monolith — the pragmatic default
In Java: Maven aggregator with submodules. Each module exposes api/ (public), domain/ + infra/ (internal). Orders module depends only on users:api, not users:domain.
ArchUnit / jMolecules / Spring Modulith enforces no class outside users.api is reachable from outside the users module.
Each module owns its DB schema. No cross-schema FKs; relationships by ID reference and module API calls.
Spring Modulith makes this first-class: boundary detection, docs, event publication for module-to-module async (decoupled like microservices but in-process).
Migration to microservices later: because modules already speak through APIs and own schemas, extraction is replace API calls with HTTP + move schema to separate DB. Tractable, not a rewrite.
Common mistakes
- Microservices because Netflix did it — most companies aren't Netflix
- Splitting too early — wrong boundaries, harder to refactor across services
- Distributed monolith — services that can't deploy independently, share DB, always release together. Worst of both worlds
- Treating microservices as 'small' — nano-services explode network calls; size should match bounded context
- Ignoring modular monolith middle ground
- No observability before going micro — debugging 30 services without tracing is impossible
Recommendation
Default to a modular monolith for almost any new system. You get most of microservices' design discipline — bounded contexts, owned data, explicit contracts — with one deployable, one DB, no distributed-systems tax. Extract a service only when forced: a specific subdomain needs independent scaling, a separate team needs independent release cadence, or an operational/availability boundary demands isolation. Microservices are a deployment-time tax that buys autonomy and isolation; pay it only when the value is real, and never to imitate big-tech architecture.
Monolith vs Microservices vs Modular Monolith
Direct Answer
Monolith = one deployable, one codebase, one DB — simplest to build and operate, but all teams share a release pipeline and a single failure domain. Microservices = many small independently deployable services, each with its own DB, communicating over the network — enables team autonomy and independent scaling, at the cost of distributed-system complexity (networking, eventual consistency, observability). Modular Monolith = single deployable but with strict module boundaries internally (each module owns its data, exposes a contract) — you get most of microservices' design discipline without the operational tax. Default to a modular monolith; extract services only when team size, scaling, or deployment cadence forces the issue.
Common Mistakes & Pitfalls
Treating microservices as universally better, or thinking 'microservices = small'. Size isn't the point — deployment independence is.
Check your understanding
Answer these without looking back at the article.
- When would you extract a single service out of a modular monolith — what triggers the move?
- How does Spring Modulith enforce module boundaries at compile time?
- What's a 'distributed monolith' and why is it the worst outcome?
- Walk through migrating a large monolith to microservices using the strangler fig pattern.
Related interview prep categories
1Want 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.