Microservices Architecture: Decomposition, Communication, and Trade-offs
Deep Dive: Database-per-Service and Why Shared Data Breaks Independent Deployments
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
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.
Deep Dive
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 .
