Monolith to Microservices Decomposition
DDD, Strangler Fig, data ownership.
Monolith to Microservices Decomposition
Decomposing a monolith into microservices is one of the highest-impact architectural changes a team can make — but it's also one of the riskiest if done incorrectly. This guide covers proven patterns for safe, incremental decomposition using Domain-Driven Design and the Strangler Fig pattern.
When to Decompose
Decomposition is warranted when:
- Deployment bottleneck — Teams wait for each other to release
- Scaling limitations — You need to scale one component but must scale everything
- Technology constraints — Different components need different tech stacks
- Team autonomy — Teams need to own and deploy independently
Don't decompose if: You have a small team (<5 developers), the monolith works fine, or you're just following a trend.
Domain-Driven Design (DDD)
Use DDD to identify natural service boundaries:
- Event Storming — Workshop with domain experts to identify domain events, commands, and aggregates
- Bounded Contexts — Identify areas where the same term means different things (e.g., "Order" in sales vs shipping)
- Context Mapping — Define relationships between bounded contexts (upstream/downstream, shared kernel, anti-corruption layer)
Strangler Fig Pattern
Incrementally replace monolith functionality with microservices:
Phase 1: Route all traffic through an API Gateway
Client → API Gateway → Monolith (all routes)
Phase 2: Extract first service behind gateway
Client → API Gateway → Monolith (most routes)
→ User Service (/api/users)
Phase 3: Continue extracting
Client → API Gateway → Monolith (shrinking)
→ User Service
→ Order Service
→ Payment Service
Phase 4: Monolith fully replaced
Client → API Gateway → User Service
→ Order Service
→ Payment Service
→ Notification ServiceDecomposition Steps
- Start with the seam — Find a module with clear boundaries and minimal dependencies
- Define the API contract — Design the service's API before extracting
- Extract data — Each service owns its data store (hardest step)
- Implement the service — Build, test, deploy independently
- Route traffic — API Gateway sends requests to the new service
- Remove from monolith — Delete the extracted code from the monolith
Data Ownership
The biggest challenge: splitting the shared database.
- Database per service — Each microservice owns its tables/schema
- No shared tables — Services communicate via APIs, not database joins
- Data duplication is OK — Eventual consistency between services is acceptable
- Event-driven sync — Publish domain events when data changes, other services consume
Common Mistakes
- Too many services too fast — Start with 2-3 services, not 50
- Distributed monolith — Services that must be deployed together aren't microservices
- Shared database — If services share a database, they're not truly independent
- Ignoring data consistency — Plan for eventual consistency from day one
- No API versioning — Breaking changes without versioning causes cascading failures
Eazy SaaS Tip: We follow the "extract the highest-value, lowest-risk service first" principle. For most applications, that's the authentication/user service. It has clear boundaries, well-defined APIs, and proving the pattern with a small service builds team confidence before tackling complex domains.