Implementing Service Decomposition Patterns
1. Decompose by Business Capability
| Aspect | Detail |
|---|---|
| Definition | One service per stable business capability (Order Mgmt, Billing, Catalog) |
| Source | Business architecture / capability map |
| Stability | Capabilities change slowly → stable boundaries |
| Pros | Aligns with business; reduces re-orgs of code |
| Cons | Requires clear business model |
Example: Capability Map → Services
Capability Service
--------------------- ----------------
Customer Management → customer-service
Product Catalog → catalog-service
Order Management → order-service
Payment Processing → payment-service
Shipping → shipping-service
2. Decompose by Subdomain
| Subdomain Type | Description | Service Strategy |
|---|---|---|
| Core | Differentiates business; high investment | Custom service, top talent |
| Supporting | Necessary but not differentiating | Custom or off-the-shelf |
| Generic | Common (auth, payments) | Buy / use SaaS / open source |
3. Decompose by Use Case
| Aspect | Detail |
|---|---|
| Definition | Service per actor's use case (e.g., "Place Order", "Track Shipment") |
| Inspiration | Use-case driven (Jacobson), Verb-Noun |
| Pros | Maps directly to user journeys |
| Cons | Risk of fragmenting cohesive data; overlap with other use cases |
4. Decompose by Volatility
| Volatility Bucket | Examples | Service Treatment |
|---|---|---|
| High Volatility | Pricing rules, promotions, UX flows | Isolate so frequent changes don't risk stable code |
| Medium Volatility | Order workflow, shipping options | Standard service |
| Low Volatility | Auth, persistence, logging | Stable platform services |
5. Self-Contained Service Pattern
| Property | Requirement |
|---|---|
| Owns Data | Private DB, no shared schema |
| Owns UI Fragment | Optionally serves its own UI module (SCS) |
| No Sync Calls | Operates without runtime dependence on others |
| Async Integration | Communicates via events / data replication |
| Failure Isolation | Other services failing doesn't break it |
Note: Self-Contained Systems (SCS) are a stricter form: each system includes UI, business logic, and data with minimal sync coupling.
6. Service per Team Pattern
| Principle | Detail |
|---|---|
| Ownership | One team owns 1-N services end-to-end |
| No Shared Services | Two teams should not co-edit one service |
| API Boundary | Cross-team interaction goes through versioned API/events |
| Cognitive Load | Limit per team (~5-9 services) |
7. Strangler Fig Pattern
| Step | Action |
|---|---|
| 1. Identify | Pick capability inside monolith to extract |
| 2. Facade | Insert routing layer (API gateway / proxy) |
| 3. Build | Implement new microservice |
| 4. Route | Gradually shift traffic from monolith to new service |
| 5. Retire | Delete old code path once 100% on new service |
Strangler Migration
[Client] → [Facade/Gateway] → ┬── /orders/* → [New Order Service] (gradually 0%→100%)
└── /* → [Legacy Monolith] (gradually 100%→0%)
8. Anti-Corruption Layer Pattern
| Aspect | Detail |
|---|---|
| Purpose | Translate between new domain model and legacy/external model |
| Placement | Adapter layer inside new service or as standalone gateway |
| Benefit | Protects new bounded context from legacy concepts leaking in |
| Cost | Extra translation code; small latency |
Example: ACL Wrapping Legacy SOAP
public class LegacyCustomerAcl {
private final LegacyCustomerSoapClient legacy;
public Customer getCustomer(CustomerId id) {
LegacyCustDTO raw = legacy.fetchCust(id.value());
return new Customer(
new CustomerId(raw.getCustNo()),
raw.getFName() + " " + raw.getLName(),
Email.of(raw.getEmailAddr()));
}
}
9. Separate Front and Backend Services
| Layer | Responsibility |
|---|---|
| Frontend Service (BFF) | Aggregates backend APIs for a specific UI client |
| Backend Service | Owns business capability and data |
| Why Separate | UI changes are frequent; backend capabilities are stable |
| Trade-off | Extra hop; mitigated by colocation/caching |
10. Understanding Decomposition Trade-offs
| Decision | Cost | Benefit |
|---|---|---|
| More services | Network ops complexity | Independent deploy/scale |
| Fewer services | Slower deploys, larger blast radius | Simpler ops |
| Decompose by capability | Requires domain expertise | Long-term stability |
| Decompose by tech layer | Easy initially | Becomes distributed monolith |
Warning: Never decompose by technical tier (UI / API / DB). This guarantees a distributed monolith.