Skip to main content
Articles/System Design/system-design-microservices-architecture
Scenario Article

Microservices Architecture: Decomposition, Communication, and Trade-offs

Deep Dive: Database-per-Service and Why Shared Data Breaks Independent Deployments

Abstract Algorithmsβ€’Mar 28, 2026
XLinkedInReddit
πŸ’‘ Executive Summary

Microservices let teams deploy and scale services independently β€” but every service boundary you draw costs you a network hop, a consistency challenge, and an operational burden.

🎯 System Scenario & Requirements

System Goal

Microservices let teams deploy and scale services independently β€” but every service boundary you draw costs you a network hop, a consistency challenge, and an operational burden.

Actors & Components

  • Edge Traffic Ingress
  • Stateless Microservices
  • Datastore Infrastructure
  • API Gateway
  • Domain Service
  • Redis Cache
  • Transactional DB
  • Application Workers

Functional Requirements

  • TLDR: Microservices let teams deploy and scale services independently β€” but every service boundary you draw costs you a network hop, a consistency challenge, and an operational burden.
  • The architecture pays off only when your team and traffic scale have genuinely outgrown a well-structured monolith.
  • Interview signal: Know the decomposition strategies (DDD bounded contexts, Strangler Fig), distinguish sync from async communication, and explain exactly why shared databases destroy independent deployability.

Constraints & Assumptions

  • The most dangerous failure mode in microservices is the cascade.
  • A single slow downstream service (say, a fraud check API timing out at 30s) can exhaust the thread pool of every caller β€” and then their callers β€” until the entire system is down over a single misbehaving dependency.
  • The column you should read first in an interview: Deployment complexity and Operational overhead .
  • These are the costs that surprise teams.

⚑ Execution Stages & Decision Trace

1

Stage 1 β€” The Monolith That Took Down Netflix for Three Days

Action / Decision:

In 2008, a database corruption event at Netflix took their entire DVD-rental and streaming platform offline for three days.

Component Behavior:

The root cause was not the database itself β€” it was the monolithic architecture.

Observable Output: Every feature, every team's code, every data access pattern was deployed as a single unit and connected to a single database.
Read Full Stage in Deep Dive ↓
πŸ“–

Deep Dive

Detailed Architectural Analysis

Scenario context

Microservices let teams deploy and scale services independently β€” but every service boundary you draw costs you a network hop, a consistency challenge, and an operational burden. The architecture pays off only when your team and traffic scale have genuinely outgrown a well-structured monolith.

Interview signal: Know the decomposition strategies (DDD bounded contexts, Strangler Fig), distinguish sync from asyn…

This walkthrough focuses on Deep Dive: Database-per-Service and Why Shared Data Breaks Independent Deployments.

Before making a design choice, clarify:

  • The database-per-service pattern is often the hardest constraint for teams migrating from a monolith, because shared databases feel efficient.
  • They are efficient β€” until they become a coupling point that makes every schema migration a cross-team coordination exercise.
  • Internals: How the Database-per-Service Contract Works The core rule is strict: no service may read from or write to another service's database .

Concepts in play: api-gateway, caching, design-patterns-gof, consistency-replication

Stage 1 β€” The Monolith That Took Down Netflix for Three Days

  • In 2008, a database corruption event at Netflix took their entire DVD-rental and streaming platform offline for three days.
  • The root cause was not the database itself β€” it was the monolithic architecture.
  • Every feature, every team's code, every data access pattern was deployed as a single unit and connected to a single database.
  • When that database went down, everything went down at once.

Observable outcome: When that database went down, everything went down at once.

Stage 2 β€” The Four Decomposition Strategies That Actually Work

  • Getting service boundaries right is the most consequential decision in a microservices migration.
  • Cut them wrong and you get a distributed monolith; cut them right and you get genuine deployment independence.
  • Domain-Driven Design and Bounded Contexts Domain-Driven Design (DDD) is the most principled approach.
  • A bounded context is a clear boundary within which a domain model applies consistently.

Observable outcome: A bounded context is a clear boundary within which a domain model applies consistently.

Stage 3 β€” From Monolith to Microservices: The Decomposition Flow

  • The diagram below shows a monolith being incrementally extracted using the Strangler Fig pattern, with each bounded context becoming an independent service behind a shared API gateway.
  • Reading the diagram: The API gateway acts as the Strangler Fig facade.
  • Extracted services (User, Order, Notification) each own a dedicated database and receive traffic directly.
  • The monolith still handles the remaining unextracted features and its shared legacy database β€” the Step 3: in progress state.
graph TD
    Client([Client]) --> GW[API Gateway / Facade]

    GW --> |"Step 1: extracted"| US[User Service]
    GW --> |"Step 2: extracted"| OS[Order Service]
    GW --> |"Step 3: in progress"| MONO[Monolith legacy features]
    GW --> |"Step 4: extracted"| NS[Notification Service]

    US --> UDB[(User DB Postgres)]
    OS --> ODB[(Order DB MySQL)]
    NS --> NDB[(Notification DB Redis)]
    MONO --> MDB[(Shared Legacy DB)]

    style MONO fill:#f9c74f,stroke:#f3722c,color:#000
    style GW fill:#4cc9f0,stroke:#4361ee,color:#000
    style MDB fill:#f9c74f,stroke:#f3722c,color:#000

Observable outcome: The monolith still handles the remaining unextracted features and its shared legacy database β€” the Step 3: in progress state.

Stage 4 β€” How Services Talk to Each Other: Sync, Async, and Discovery

  • Once services are split, they need to communicate.
  • The choice between synchronous and asynchronous communication is one of the most impactful decisions in microservices design.
  • The diagram below shows a typical microservices deployment β€” an API gateway at the entry point, independent business capability services in the middle tier, and each service owning its isolated data store.
  • Async side effects (like notifications) route through a message broker rather than blocking the caller.
flowchart TD
    Client["Client (Browser or Mobile)"] --> GW["API Gateway (Auth, Routing, Rate Limiting)"]
    GW --> SvcA["Order Service"]
    GW --> SvcB["User Service"]
    GW --> SvcC["Inventory Service"]
    SvcA --> DBA[("Order DB (MySQL)")]
    SvcB --> DBB[("User DB (PostgreSQL)")]
    SvcC --> DBC[("Inventory DB (Redis)")]
    SvcA -->|"async event"| MQ["Message Broker (Kafka)"]
    MQ --> SvcD["Notification Service"]
    SvcD --> DBD[("Notification DB (Redis)")]

Observable outcome: Async side effects (like notifications) route through a message broker rather than blocking the caller.

Stage 5 β€” Real-World Applications: Netflix's 700 Services and Segment's Reversal

  • Two production case studies at opposite ends of the microservices spectrum show that the architecture is a tool, not a destination.
  • Netflix (2008–2016): 1 service β†’ 700+ services.
  • After the 2008 database outage, Netflix had a concrete and expensive problem: one failure domain took down everything.
  • Their traffic was also growing 10x year-over-year.

Observable outcome: Their traffic was also growing 10x year-over-year.

Stage 6 β€” Spring Cloud: How It Wires Microservices Together

  • Spring Cloud is the de-facto Java framework for microservices infrastructure.
  • It provides service discovery (Eureka), configuration management (Config Server), API gateway (Spring Cloud Gateway), and resilience (Resilience4j circuit breakers) β€” all integrating with Spring Boot applications via an…
  • Service Registration with Eureka Each service registers with Eureka on startup by declaring its application name and the Eureka server URL.
  • The client pulls the live registry at startup and polls for updates at a configurable interval, so it always has a fresh list of available instances for each dependency.

Observable outcome: The client pulls the live registry at startup and polls for updates at a configurable interval, so it always has a fresh list of available instances for each dependency.

End-to-end outcome

After working through the stages, you should be able to explain:

  • Service boundaries set in year one are hard to change.
  • Wrong decomposition creates tight coupling at the network layer instead of the code layer.

Alternatives considered

Synchronous vs Asynchronous Communication Flow

Reading the diagram: The checkout path is synchronous β€” the Order Service blocks on inventory validation because correctness requires it.

Decision Guide: When Microservices Help and When They Hurt

The Segment reversal happened because they decomposed before the organizational pressure existed.

Decision Point: Synchronous vs Asynchronous in Practice

Decision Point: Synchronous vs Asynchronous in Practice

Failure and degraded modes

Trade-offs and Failure Modes: Cascade Failures and the Patterns That Contain Them

  • Detection: The most dangerous failure mode in microservices is the cascade.
  • User or operator impact: The most dangerous failure mode in microservices is the cascade.

Microservices vs Monolith: The Trade-offs Nobody Puts on the Architecture Slide

  • Detection: The column you should read first in an interview: Deployment complexity and Operational overhead .
  • User or operator impact: The column you should read first in an interview: Deployment complexity and Operational overhead .

Share this case study

Discuss architecture trade-offs and lessons with your team.

Share:XLinkedInReddit