Service Decomposition
Service decomposition splits a system into independently deployable services aligned to business capabilities or subdomains — not technical layers.
Introduction
Service decomposition splits a system into independently deployable services aligned to business capabilities or subdomains — not technical layers. Netflix's migration from monolith to 700+ microservices succeeded because decomposition followed bounded contexts (billing, playback, recommendations), not CRUD tables.
Real production story
Netflix's 2012 "API team owns everything" monolith meant a subtitle bug fix required deploying the entire streaming stack. A playback engineer's schema migration broke billing for 90 minutes during a Friday deploy — the classic "distributed monolith waiting to happen" inside one WAR file.
The decomposition program used Domain-Driven Design workshops: identify bounded contexts, assign two-pizza teams, define service contracts before code splits. Playback separated first — not because it was easiest, but because it had the clearest domain language and highest independent scaling need. Each extraction used the strangler fig pattern with dual-write reconciliation. Five years later, team deploy frequency went from weekly coordinated releases to 4000+ production deploys per day across services.
Business problem
Business pressure: Netflix global expansion required independent scaling of playback CDN logic vs billing compliance vs recommendation ML — one deployable unit could not optimize all three.
- Revenue at risk: Correlated deploy failures during peak streaming hours directly map to subscriber churn and CDN waste.
- Engineering velocity: 200 engineers in one repo created merge queue paralysis — features waited weeks for unrelated team's schema migration.
- Compliance / trust: PCI and regional data residency require physically separable billing services — decomposition is compliance architecture.
Architecture overview
Service decomposition strategies: (1) by business capability, (2) by subdomain (DDD), (3) by volatility — never by technical layer (presentation-service, database-service).
- Definition: Each service owns one bounded context's data and behavior; communicates via published APIs or events.
- When to adopt: Multiple teams, proven domain boundaries, independent scaling/deploy requirements.
- When to defer: Unvalidated product, <10 engineers, fuzzy domain — modular monolith first.
- Operability: Each decomposed service gets its own SLO, on-call rotation, and runbook before extraction completes.
Architecture motivation
Why architects care: Decomposition is irreversible organizational glue — wrong cuts create distributed monoliths with network latency and no isolation benefits.
- Force: Independent scaling, deployment, and failure domains per business capability.
- Constraint: Cannot stop feature development for 18-month rewrite — incremental strangler required.
- Outcome: Services map to team ownership; contracts versioned; shared nothing except async events.
Internal architecture
Netflix capability-based decomposition — services by subdomain, not layer:
┌─────────────────┐│ Zuul / Gateway │└────────┬────────────┘┌───────────────────┼───────────────────┐▼ ▼ ▼┌─────────────┐ ┌─────────────┐ ┌─────────────┐│ PLAYBACK │ │ BILLING │ │ RECOMMEND ││ service │ │ service │ │ service ││ (CDN, DRM) │ │ (PCI zone) │ │ (ML rank) │└──────┬──────┘ └──────┬──────┘ └──────┬──────┘│ │ │▼ ▼ ▼Cassandra PostgreSQL Feature store(viewing state) (subscriptions) (embeddings)✗ WRONG: "DatabaseService" + "BusinessLogicService" + "UIService"✓ RIGHT: capability owns its data + API + deploy pipeline
Data flow
Primary path: Client requests playback manifest → gateway routes to Playback service → Playback reads viewing state from owned Cassandra → async event TitleStarted to Kafka → Recommend service updates taste profile without synchronous coupling.
- Write path: Billing service owns subscription mutations; Playback never writes billing tables — calls Billing API or consumes events.
- Read path: Each service serves denormalized read models; cross-service reads via API or cached materialized views.
- Async path: Domain events as integration contract; choreography for non-critical paths, orchestration for money movement.
System design diagram
Two diagrams show the Service Decomposition topology and the primary request/event path used in production at scale.
Production code example
Decomposition readiness scorecard — Netflix platform team gate before extraction:
// Service extraction readiness checklist (automated where possible)interface ExtractionReadiness {boundedContextDocumented: boolean; // ADR + context mapownedSchema: boolean; // no cross-service FKpublishedApiVersioned: boolean; // OpenAPI / protobuf semverindependentCiCd: boolean; // deploy without sibling servicessloDefined: boolean; // latency + availability targetsonCallRotation: boolean; // two-pizza team assignedcontractTestsPassing: boolean; // Pact / protobuf compatstranglerRouteConfigured: boolean; // % traffic to new service}async function gateExtraction(service: string): Promise<void> {const score = await assessReadiness(service);const blockers = Object.entries(score).filter(([, ok]) => !ok).map(([k]) => k);if (blockers.length) {throw new ExtractionBlockedError(`${service} not ready: ${blockers.join(", ")}`);}await platform.registerService({ name: service, tier: "production" });}// Strangler routing — increment % to new serviceconst routes = [{ match: { header: "X-Canary-User" }, target: "playback-v2" },{ match: { weight: 5 }, target: "playback-v2" },{ match: { default: true }, target: "playback-v1" },];
Enterprise case study
Netflix monolith-to-microservices (2009–2016): DDD-driven decomposition enabled 4000+ deploys/day and independent playback scaling during global launch.
- Before: Single WAR, weekly coordinated deploys, correlated outages.
- Decision: Bounded context workshops, strangler extraction, event-driven integration between contexts.
- After: Team autonomy, playback scaled to 200M+ subscribers without billing redeploys.
Trade-offs
- Isolation vs operational cost: 700 services mean 700 deploy pipelines, dashboards, and on-call rotations — platform team mandatory.
- Consistency vs autonomy: No distributed transactions — sagas and eventual consistency replace ACID comfort.
- Decomposition granularity: Too fine = chatty network; too coarse = mini-monolith — two-pizza team heuristic guides size.
Security considerations
Security is architectural: Decomposition enables PCI zone isolation — Billing service in hardened network segment, Playback in CDN-facing DMZ.
- Identity: Service mesh mTLS between services; gateway validates user JWT once.
- Data: Each service minimizes PII — Recommend gets hashed title IDs, not billing addresses.
- Supply chain: Per-service SBOM and vulnerability SLAs — blast radius contained per deploy unit.
Scalability analysis
Scale dimensions: Netflix decomposed playback first because CDN edge logic scaled differently from billing CRUD — decomposition follows scaling heterogeneity.
- Horizontal scale: Playback autoscales on concurrent streams; Billing scales on subscription churn rate — independent HPA.
- Hot spots: Recommend service GPU inference — separate fleet from JVM billing services.
- Cost: Service count drives baseline infra overhead — consolidate until scaling or team boundaries force split.
Failure scenarios
What breaks: Decompose by URL path without data ownership — creates distributed monolith with synchronous chains.
- Chatty decomposition: 12 synchronous calls per page load — p99 latency equals sum of services.
- Shared database extraction: Two "services" one DB — false decomposition, true coupling.
- Big bang rewrite: 18-month project with no production value — strangler with measurable slices wins.
Staff engineer insights
- Decompose when organizational pain exceeds operational pain — not because microservices are fashionable.
- Netflix's lesson: the first service to extract should have the clearest domain boundary, not the easiest code.
- If two "services" always deploy together and share a database, you have one service with extra network hops.
Interview questions
Interview Prep
Practice concise answers, then expand each card for the explanation.
1AdvancedQuestionHow do you decide service boundaries for decomposition?+
Answer
Follow-up
2AdvancedQuestionDescribe Netflix's approach to incremental decomposition.+
Answer
Follow-up
3AdvancedQuestionWhat signals indicate you decomposed too finely?+
Answer
Follow-up
Architecture review questions
- Is each service aligned to a bounded context or business capability, not a technical layer?
- Does each service own its data store with no cross-service foreign keys?
- Are integration contracts versioned (OpenAPI/protobuf) with consumer-driven contract tests?
- Can each service deploy independently without coordinated releases?
- Is there a strangler migration plan with traffic percentage and rollback?
- Does each service have defined SLO, on-call owner, and runbook before production cutover?
Summary
Service decomposition at Netflix scale means aligning deployable units to bounded contexts with owned data, versioned contracts, and strangler migrations. Staff architects gate extraction on readiness scorecards and resist cuts that produce chatty synchronous chains or shared-database false services.