Module 2: Microservices & Service Decomposition: Case Studies
These case studies focus on the difference between services that create autonomy and services that merely distribute pain.
Case Study 1: Uber Domain-Oriented Microservice Architecture
Scenario: A microservice estate grows so large that individual services are no longer the right unit of understanding. Teams need a higher-level grouping around domains.
Source anchor: Uber's Introducing Domain-Oriented Microservice Architecture, which describes organizing related microservices into domains and layers.
Module concepts: domain-oriented services, service ownership, boundary grouping, platform complexity.
Wrong Approach
Keep decomposing into smaller services without a domain-level map.
Better Approach
Group services by business domain and clarify dependencies:
Domain:
marketplace
Services:
matching, pricing, dispatch
External contract:
domain API/events, not every internal service
Tradeoff Table
| Choice | Gain | Cost |
|---|---|---|
| many standalone services | local ownership | system map becomes unreadable |
| domain grouping | clearer ownership and APIs | governance at domain layer |
| platform layer | shared capabilities | platform coupling |
| monolith module | simpler runtime | less independent deployability |
Required Artifact
Draw a domain-oriented service map with internal services, public contracts, and forbidden cross-domain calls.
Case Study 2: Shared Database Distributed Monolith
Scenario: Order, billing, and fulfillment services deploy separately but read and write the same tables. A schema change requires a coordinated deploy of all services.
Source anchor: Chris Richardson's Database per service pattern explains why private data ownership is central to microservice autonomy.
Module concepts: database-per-service, shared database, coupling, distributed monolith.
Wrong Approach
"Separate deployables are enough."
Independent deployment is hollow if all services are coupled through tables.
Better Approach
Move toward data ownership:
Orders owns:
orders, order_items
Billing owns:
invoices, payments
Fulfillment owns:
shipments
Integration:
APIs/events/read models
Tradeoff Table
| Choice | Gain | Cost |
|---|---|---|
| shared DB | easy joins and transactions | schema coupling |
| DB per service | autonomy | distributed consistency |
| replicated read model | query convenience | freshness and pipelines |
| reporting warehouse | analytics | ETL/ELT delay |
Required Artifact
Create a service data-ownership matrix: table, owner, writers, readers, integration path, migration plan.
Case Study 3: Netflix Hystrix And Failure Containment
Scenario: A recommendation service is slow. Without timeouts and isolation, checkout threads wait on recommendations and checkout fails too.
Source anchor: Netflix's Introducing Hystrix for Resilience Engineering, describing controls for latency and failure between distributed services.
Module concepts: timeout, circuit breaker, bulkhead, fallback, cascading failure.
Wrong Approach
Every service call waits as long as the downstream wants.
Better Approach
Contain failure:
Timeout:
recommendation call max 150 ms
Circuit:
open after error/latency threshold
Bulkhead:
separate pool from checkout-critical calls
Fallback:
show popular products or omit panel
Tradeoff Table
| Choice | Gain | Cost |
|---|---|---|
| no timeout | simple | cascading latency |
| timeout | protects caller | false failures if too aggressive |
| circuit breaker | stops hammering dependency | fallback path needed |
| bulkhead | isolates resources | capacity planning complexity |
Required Artifact
Write a dependency resilience contract: timeout, retry, circuit, fallback, bulkhead, and metric.
Case Study 4: Backend For Frontend Instead Of One Giant API
Scenario: Web, iOS, Android, and partner API clients all use the same endpoint. Every response contains fields some clients need and others cannot handle.
Source anchor: Sam Newman popularized the Backend for Frontend pattern for client-specific API surfaces. See Pattern: Backends For Frontends.
Module concepts: BFF, client-specific contract, API gateway, coupling.
Wrong Approach
One API shape must satisfy all clients forever.
Better Approach
Use BFFs when client workflows differ:
Mobile BFF:
bandwidth-aware compact response
Web BFF:
dashboard composition
Partner API:
stable external contract
Tradeoff Table
| Choice | Gain | Cost |
|---|---|---|
| one generic API | fewer services | bloated contract |
| BFF | client fit | more deployables |
| API gateway only | centralized routing | not domain composition by itself |
| GraphQL | flexible fields | resolver/cost governance |
Required Artifact
Compare one endpoint as generic API vs web BFF vs mobile BFF.
Case Study 5: Strangler Migration With Service Extraction
Scenario: A monolith's billing module is painful but not isolated. The team wants to extract billing first because it has clear business ownership.
Source anchor: Martin Fowler's Strangler Fig Application frames gradual replacement through routing and coexistence.
Module concepts: strangler pattern, service extraction, seam, migration, rollback.
Wrong Approach
Extract billing tables and code in one release.
Better Approach
Migrate in phases:
1. Define billing API in monolith.
2. Route internal callers through the seam.
3. Move read model first.
4. Dual-write or outbox events during transition.
5. Switch authority after reconciliation.
Tradeoff Table
| Choice | Gain | Cost |
|---|---|---|
| big extraction | quick target | high cutover risk |
| strangler | incremental proof | temporary duplication |
| read-first extraction | low risk | not full autonomy yet |
| write authority switch | real service boundary | data migration risk |
Required Artifact
Write an extraction plan with seam, first endpoint, data ownership move, rollback, and success metric.
Source Map
| Source | Use it for |
|---|---|
| Uber Domain-Oriented Microservice Architecture | organizing large microservice estates |
| Microservices.io: Database per service | service data ownership |
| Netflix Hystrix | resilience primitives around service calls |
| Sam Newman: BFF | client-specific API boundary |
| Martin Fowler: Strangler Fig | incremental service extraction |
Completion Standard
- At least three artifacts are completed.
- At least one service map names ownership and data boundaries.
- At least one dependency has a resilience contract.
- At least one migration plan includes rollback.