Skip to main content

Strategic Decomposition to Services

Break monoliths into services aligned with bounded contexts

TL;DR

Strategic decomposition breaks monoliths into services aligned with bounded contexts (DDD principle). Identify service boundaries based on business capability, not technical layers. Use the Strangler Pattern for safe, incremental migration: build new service alongside monolith, route requests via API Gateway, gradually shift load, then decommission old code. Benefits: independent scaling, team autonomy, deployment velocity. Risks: increased complexity, eventual consistency, distributed debugging. Plan 3-6 months per service for proper decomposition.

Learning Objectives

  • Identify bounded contexts and service boundaries using DDD
  • Map monolith code to contexts and dependencies
  • Prioritize decomposition: which services first (ROI analysis)
  • Apply Strangler Pattern for safe, incremental migration
  • Manage data consistency and ownership across service boundaries
  • Design APIs, contracts, and event schemas
  • Monitor and validate decomposition progress
  • Handle rollback and failure scenarios

Motivation: When to Decompose

Decompose when monolith becomes:

  • Hard to change: Multiple teams step on each other; deployment coordination pain
  • Slow to deploy: Small change requires full testing, deployment; 30+ minutes from code to prod
  • Uneven scaling: One feature needs 10x more instances; forced to scale entire monolith
  • Recruitment bottleneck: New engineers scared of touching monolith; high onboarding time
  • Technology blocker: Want to use different languages/frameworks for different domains

Do NOT decompose:

  • Small, fast-changing systems (simplicity > benefits)
  • Early-stage startups (product-market fit unclear)
  • When you don't understand your domain well (boundaries fuzzy)
  • Single team owning everything (no team scaling benefit)
Monolith vs Microservices: When does the crossover happen?

Domain Analysis: Identifying Bounded Contexts

Before coding, understand your domains:

Step 1: List Business Capabilities
e-commerce platform capabilities:
- Product Catalog (browse, search, recommendations)
- Orders (create, track, history)
- Payments (authorize, capture, refund)
- Shipping (calculate cost, track)
- Inventory (stock, reservations)
- Notifications (email, SMS, push)
- Customer Accounts (profile, preferences)
- Reviews & Ratings (CRUD, moderation)

Step 2: Group into Bounded Contexts
Each context has:
- Clear responsibility (one reason to change)
- Distinct ubiquitous language
- Own data model
- Limited external dependencies

Initial Contexts:
1. Catalog Context (Products, Search, Recommendations)
2. Order Context (Orders, Order Items)
3. Payment Context (Payments, Transactions)
4. Shipping Context (Shipments, Tracking)
5. Inventory Context (Stock, Reservations)
6. Notification Context (Email, SMS, Push)
7. Customer Context (Accounts, Profiles)

Step 3: Analyze Dependencies
Order Context
├─ depends on: Inventory (check stock)
├─ depends on: Product Catalog (product details)
├─ depends on: Customer (shipping address)
├─ publishes: OrderCreated, OrderShipped
├─ subscribes to: PaymentConfirmed
└─ risk: HIGH (many dependencies)

Notification Context
├─ depends on: none (subscribes to events)
├─ publishes: none
└─ risk: LOW (loosely coupled)

Step 4: Calculate Extraction Cost vs Benefit
Metrics:
- Code size (lines extractable from monolith)
- Coupling to others (dependencies)
- Deployment frequency needed
- Scaling requirements
- Team size assigned to context
- Business value

Scoring:
┌─────────────────────────────────────┐
│ Service │ ROI │ Effort │ Risk │
├─────────────────────────────────────┤
│ Payments │ HIGH │ MED │ MED │ ✓ First
│ Notifications│ MED │ LOW │ LOW │ ✓ Second
│ Shipping │ MED │ HIGH │ HIGH │ ✓ Third
│ Inventory │ HIGH │ HIGH │ HIGH │ ✗ Later
└─────────────────────────────────────┘

Step 5: Prioritize Extraction Order
Ideal services to extract first:
1. HIGH value, LOW effort
2. Loosely coupled
3. HIGH business impact
4. Clear boundaries
5. High deployment frequency

Strangler Pattern: Incremental Migration

Safe migration in phases:

Build New Payment Service:
✓ Greenfield implementation
✓ All unit + integration tests
✓ Own database (separate schema)
✓ REST API matching monolith's payment API
✓ Event publisher for PaymentConfirmed
✓ Ready for requests, but not receiving any yet

Monolith Status:
✓ Payment code still present
✓ No awareness of new service
✓ Handling all payment requests
✓ Fully operational

Risk Assessment:
✓ ZERO impact on production (new service not live)
✓ Only risk: development/testing

Timeline:
Week 1: Design API, database schema, architecture
Week 2: Implement core payment logic
Week 3: Implement payment gateway integration
Week 4: Test, fix bugs, performance tune

Deliverable:
✓ Payment Service artifact (Docker image, JAR, etc.)
✓ Documentation
✓ Test coverage 80%+

Data Ownership and Consistency

Critical decisions when decomposing:

From shared database to service-owned data
Rule 1: One Service Owns Data
✓ Payment Service owns payments table
✓ Only Payment Service writes to payments
✓ Other services READ via API (not direct DB access)

Rule 2: No Shared Database
✗ BAD: Order Service and Payment Service share schema
✓ GOOD: Each has separate database

Rule 3: Access Data via API or Events
Order Service wants to know if payment succeeded:
✓ GOOD: Call Payment Service API
GET /payments/{paymentId}

✓ GOOD: Subscribe to PaymentConfirmed event
when PaymentConfirmed(orderId, success)
update order.paymentStatus = success

✗ BAD: Query payments table directly
SELECT * FROM payments WHERE order_id = ?

Rule 4: Manage Consistency Explicitly
Order + Payment are eventually consistent:
- Create Order (state: PENDING_PAYMENT)
- Request Payment Service
- If Payment fails: Order state becomes PAYMENT_FAILED
- If Payment succeeds: Order state becomes CONFIRMED
- Payment Service publishes PaymentConfirmed
- Order Service receives and marks CONFIRMED

Transactional consistency (ACID) LOST
Eventual consistency (all updates eventually propagate) GAINED

Common Pitfalls and How to Avoid Them

Decomposition Checklist

  • Are service boundaries clearly aligned with bounded contexts?
  • Have you analyzed dependencies between contexts?
  • Is data ownership clear (which service owns which tables)?
  • Are inter-service dependencies documented and minimal?
  • Do services communicate via APIs and events (NOT shared DB)?
  • Is the strangler pattern planned (don't rewrite everything)?
  • Is data migration strategy documented (copy, sync, validate)?
  • Are monitoring and alerts in place for the new service?
  • Is rollback procedure tested and documented?
  • Can each service be deployed independently?
  • Do teams understand their service ownership and dependencies?
  • Is the next service already being analyzed for decomposition?

Decision Questions

Before decomposing a service, ask:

  1. Is this bounded context stable? (Will requirements change frequently?)
  2. Will this service be deployed frequently? (Multiple times per week?)
  3. Does this need independent scaling? (Different traffic patterns than monolith?)
  4. Are the dependencies minimal? (How many other services must it call?)
  5. Can a team own this independently? (Clear responsibility, success metrics?)
  6. What's the ROI? (Developer velocity gain vs operational complexity?)

If YES to 4+ questions: decompose. If NO to most: stay in monolith longer.

One Takeaway

Decompose strategically based on business domains (DDD), not technical layers. Use the Strangler Pattern to migrate safely and incrementally. Start with loosely-coupled, high-value services. Invest in monitoring and data consistency strategies before moving traffic. Decomposition is a 6-12 month investment for most systems; plan accordingly.

Next Steps

  • Read Domain-Driven Design by Eric Evans (bounded contexts foundation)
  • Study Build Microservices by Sam Newman (strangler pattern details)
  • Practice Domain storytelling to identify contexts
  • Plan your first service decomposition (2-3 months timeline)
  • Set up API Gateway and event bus infrastructure

References