Service Decomposition Strategies
IntermediateDecompose by business capability, by subdomain (DDD), or by verb (action); wrong boundaries are the primary cause of microservices complexity and distributed monoliths.
Overview
Service decomposition is the most consequential decision in microservices architecture. Poor boundaries result in chatty networks, distributed monoliths, or nano-services that are harder to manage than what they replaced. The three main strategies are: decompose by business capability (stable organisational functions), by DDD subdomain (bounded contexts), and by use case or verb (each service owns one business action). The "strangler fig" pattern is the recommended migration path from a monolith — new features are built as services while the monolith is gradually hollowed out.
Decompose by Business Capability
A business capability is a stable function the organisation performs, e.g. Order Management, Customer Management, Billing. Each capability becomes a service with its own data store. This aligns with Conway's Law — teams map to services.
// Business capabilities → services
// Capability: Order Management
// Service: order-service
// Owns: orders DB table, order lifecycle state machine
// Capability: Customer Management
// Service: customer-service
// Owns: customers DB, profile management
// Capability: Billing
// Service: billing-service
// Owns: invoices, payment records
// Anti-pattern — shared database across services:
// order-service → JOIN customers → violates service independence
// ✗ SELECT o.*, c.email FROM orders o JOIN customers c ON o.customer_id = c.id
// Correct — order-service calls customer-service API:
// ✓ GET /customers/{id} → returns CustomerDTO to order-serviceDecompose by Subdomain (DDD)
DDD bounded contexts define explicit linguistic boundaries. Each bounded context becomes one service (or a small cluster of related services). Ubiquitous language inside a context keeps the model consistent; context maps define inter-service integration.
// Bounded contexts in an e-commerce platform
// "Order" context — order-service
// Ubiquitous language: Order, LineItem, Fulfilment, ShipmentStatus
// "Catalogue" context — catalogue-service
// Ubiquitous language: Product, Variant, Inventory, PriceList
// Note: "Product" means something different in each context!
// Context Map — how they integrate
// ① Conformist: order-service conforms to catalogue-service's Product model
// ② Anti-Corruption Layer (ACL): order-service translates catalogue concepts
// into its own domain model (LineItem, SKU) via an adapter
// ACL example
public class CatalogueAdapter {
private final CatalogueClient catalogueClient;
public LineItemDetails getLineItemDetails(String sku) {
ProductDTO product = catalogueClient.getProduct(sku); // external model
return new LineItemDetails( // internal model
product.getSku(),
product.getDisplayName(),
Money.of(product.getPriceCents(), "GBP")
);
}
}Strangler Fig Migration
The strangler fig pattern incrementally replaces a monolith. New functionality is built as services; existing features are migrated one capability at a time. An API gateway or reverse proxy routes requests to the service or to the monolith based on the path.
# Step 1 — route new capability to microservice via API gateway (nginx example)
# Old path goes to monolith; new /api/v2/orders goes to order-service
location /api/v2/orders {
proxy_pass http://order-service:8080;
}
location / {
proxy_pass http://monolith:8080; # all other traffic still hits the monolith
}
# Step 2 — strangler: migrate /api/v1/orders from monolith to order-service
# Deploy order-service, run dual-write, switch routing, then deprecate monolith endpoint
# Step 3 — extract customer capability
# Build customer-service, migrate data, update routing
# Eventually the monolith handles nothing and is decommissionedKey Points to Remember
- 1Decompose by business capability, DDD bounded context, or use case — choose the strategy that fits your team structure.
- 2Wrong service boundaries cause distributed monoliths (tight coupling) or nano-services (excessive overhead).
- 3Each service must own its own data store — no shared databases.
- 4Anti-Corruption Layers translate between bounded contexts to protect the internal model.
- 5Conway's Law: team structure influences service boundaries; align them intentionally.
- 6Use the strangler fig pattern to migrate a monolith incrementally without a big-bang rewrite.
Interview Questions
Sign in to ask AriaWhat are the main strategies for decomposing a monolith into microservices?
What is a bounded context and how does it guide service decomposition?
What is the strangler fig pattern and when would you use it?
What makes a service boundary "wrong" and what are the symptoms?
What is an Anti-Corruption Layer and why is it needed between services?
Ask Aria about Service Decomposition Strategies
Your personal AI tutor — ask anything about this concept
Revision Status
Personal Notes
Sign in to save personal notes for this topic.
Discussion
Sign in to join the discussion.