Enterprise Architecture Patterns Tutorial 0/65 lessons ~6 min read Lesson 24

    Service Decomposition

    Service decomposition splits a system into independently deployable services aligned to business capabilities or subdomains — not technical layers.

    Course progress0%
    Focus
    18 guided sections
    Practice signal
    Examples included
    Career prep
    Interview Q&A included

    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:

    text
    ┌─────────────────┐
    │ 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.

    Service Decomposition — system view
    API Gateway
    Edge
    Playback svc
    Core
    Billing svc
    Data
    Recommend svc
    Async
    High-level topology for Service Decomposition.
    Service Decomposition — request / event flow
    Client request
    Ingress
    Route by cap
    Store
    Service logic
    Store
    Owned store
    Emit
    Follow this path when reviewing production designs.

    Production code example

    Decomposition readiness scorecard — Netflix platform team gate before extraction:

    typescript
    // Service extraction readiness checklist (automated where possible)
    interface ExtractionReadiness {
    boundedContextDocumented: boolean; // ADR + context map
    ownedSchema: boolean; // no cross-service FK
    publishedApiVersioned: boolean; // OpenAPI / protobuf semver
    independentCiCd: boolean; // deploy without sibling services
    sloDefined: boolean; // latency + availability targets
    onCallRotation: boolean; // two-pizza team assigned
    contractTestsPassing: boolean; // Pact / protobuf compat
    stranglerRouteConfigured: 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 service
    const 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.

    3 questions
    1AdvancedQuestionHow do you decide service boundaries for decomposition?+

    Answer

    Use DDD bounded contexts and business capabilities — not nouns from ERD. Ask: can this team own data, API, and deploy independently? Do changes here correlate with a distinct business verb (play, bill, recommend)? Run event storming; if aggregate lifecycles cross boundaries, reconsider the cut.

    Follow-up

    What is wrong with decomposing by CRUD entity?
    2AdvancedQuestionDescribe Netflix's approach to incremental decomposition.+

    Answer

    Strangler fig: proxy routes traffic slice to new service, dual-write with reconciliation, contract tests at seam, expand traffic percentage. Never big-bang. First extraction targets high-value boundary (playback), not easiest code. Platform provides paved-road templates before team 2 extracts.

    Follow-up

    How do you handle shared authentication during migration?
    3AdvancedQuestionWhat signals indicate you decomposed too finely?+

    Answer

    Synchronous chains >3 deep for core user journeys; deploy correlation >80% between services; p99 latency dominated by network; teams need coordinated releases for single feature. Remedy: merge services or replace sync with events and read models.

    Follow-up

    How does the two-pizza team rule guide service size?

    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.

    Ready to mark this lesson complete?Track your journey across the entire course.