Migrating a Modular Monolith to Microservices
Fast recall
Quick revision
Core answer
Pragmatic architectural migration thinking; recognizing microservices are not the goal
Extracting services too early; extracting by technical layer (auth-service, email-service) instead of bounded context; shared database; no observability investment
Discuss the Strangler Fig, bounded contexts vs technical decomposition, data ownership patterns, transaction patterns, team topologies, and when microservices are the wrong answer
Interview-ready guide
Interview answer
Microservices are not the goal. Team autonomy, independent scaling, and fault isolation are the goals. Ask what problem you're solving before planning the migration.
The wrong path
- Extract by technical layer (auth-service, email-service); every feature requires coordinated deployment of 5 services
- Share a database across services; schema changes require coordination; distributed monolith with more operational overhead
- Skip observability; debugging takes days
- Extract before the monolith is modular; tight coupling hurts more across the network
The right path — 6 phases
Phase 1: Modularize the monolith (2 to 6 months)
- Identify bounded contexts via event storming
- Split packages by context: orders, inventory, payment
- Each module has its own DB schema; foreign keys only within own schema
- Cross-module communication via explicit interfaces
- Enforce with ArchUnit or Spring Modulith
- Internal events (OrderPlaced) instead of direct method calls
- This is the highest-value work; if you stop here, you still win most benefits
Phase 2: Establish platform (parallel, 2 to 3 months)
- Observability: distributed tracing, centralized logs, metrics
- CI/CD template; service template with logging, health, metrics, auth pre-wired
- API Gateway (Kong, Envoy, AWS API Gateway)
- Event bus (Kafka plus schema registry)
- On-call practices: PagerDuty, runbooks, blameless postmortems
- Without these, extracting creates chaos
Phase 3: Extract first service (2 to 4 months)
- Pick easiest high-value bounded context
- Well-defined API surface, clear ownership, high-change part
- Typical first: search, notifications, reporting (leaf nodes)
- Build new service, deploy alongside monolith
- Route via API Gateway; migrate data via dual-write or CDC
- Remove code from monolith
Phase 4: Strangler Fig for more extractions (6 to 12 months)
- One at a time; stabilize; next
- Parallel extractions multiply risk
- Monolith shrinks with each extraction
Phase 5: Handle data ownership (throughout)
- Database per service; hard rule
- Data duplication: services have snapshots, not live joins
- CDC (Debezium) streams changes between services
- Event-carried state transfer
- No distributed transactions; use sagas + outbox pattern
- Design for eventual consistency
Phase 6: Team organization (throughout)
- Conway's Law: systems mirror communication structures
- One service equals one team ideally
- Team owns deploy, monitoring, on-call
- Avoid 'shared services' teams (creates bottleneck)
- Platform team supports but doesn't own feature services
Key risks
Distributed monolith trap
- Services still share DB, deploy together
- Double operational complexity for zero benefit
- Rule: if two services can't deploy independently, they shouldn't be separate
Wrong decomposition
- Extract by technical layer; every feature spans services
- Decompose by domain, not technology
Latency multiplication
- In-process: nanoseconds; cross-service: milliseconds
- 10-hop chain equals 100ms+ baseline
- Bound by latency budget when extracting
Observability debt
- Without distributed tracing, debugging takes days
- Invest before scaling service count
On-call fatigue
- Each service has alerts; each team carries pagers
- Tune ruthlessly or burn out teams
When microservices are wrong
- Small team (< 20 engineers); modular monolith better
- Simple domain without real autonomy pressure
- Pre-product-market-fit startup
- No platform engineering capacity
Successful 'microservices' stories often look modest
- Shopify: modular monolith with selected extractions
- Basecamp: stayed monolithic
- Stack Overflow: monolithic .NET with few supporting services
- Netflix, Amazon, Uber: hundreds of services but these are 1000+ engineer orgs
Reverse migration is fine
- Some orgs merged services back when extraction didn't pay off
- Valid move if data supports it
DORA metrics prove success
- Deployment frequency (target: daily per team)
- Lead time for change (commit to prod)
- Mean time to recovery (MTTR)
- Change failure rate (under 15%)
- If teams deploy independently daily, microservices work
- If they deploy together weekly, you've got a distributed monolith
The modular monolith is often the right answer
- Spring Modulith, DDD, ArchUnit give 80% of microservices benefits at 20% of cost
- Only extract when specific pain demands it
- Most successful 'migrations' end with 3 to 5 services plus modular core
The strategic answer
- Don't ask 'how to migrate to microservices'; ask 'what problem am I solving'
- Modularize the monolith first
- Build platform before extracting
- Strangler Fig for gradual migration
- Decompose by bounded context, not technical layer
- Data ownership is hardest; database per service, events for sync
- Pace extractions; one at a time
- Measure with DORA metrics
- Stop when further extraction doesn't solve a real problem
- Microservices have costs; be honest about when they're worth paying
Migrating a Modular Monolith to Microservices
Direct Answer
Don't start by 'extracting services' — start by strengthening module boundaries inside the monolith (each module as a hexagonal mini-app, own DB schema, communicate via interfaces or events). Extract services only when you have proven bounded contexts, team autonomy pain, and scaling pressure. Use the Strangler Fig pattern: route traffic at the edge; gradually redirect new routes to extracted services; keep old behind facade until all consumers migrate. Expect the hardest parts to be data ownership (shared DB tables), cross-service transactions (replace with sagas/outbox), and operational maturity (observability, CI/CD, on-call per service). Most successful 'microservices migrations' are actually good modular monoliths with 3–5 services extracted, not 50.
Common Mistakes & Pitfalls
Extracting services too early; extracting by technical layer (auth-service, email-service) instead of bounded context; shared database; no observability investment
Check your understanding
Answer these without looking back at the article.
- What is the Strangler Fig pattern and how does it differ from 'big bang' migration?
- How do you handle distributed transactions across extracted services?
- What are DORA metrics and why do they matter for microservices migrations?
- When should you reverse a microservices extraction and merge back to the monolith?
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.