Microservices Patterns - Complete Internal Map
// Decomposition · communication · data · reliability · observability · security · deployment · transactions
46 total patterns
Decomposition
Communication
Data
Reliability
Transactions
01Decomposition Patterns- How to split a system into microservices
📋Decompose by Business Capabilitydecompose
Split services around stable business capabilities such as users, orders, billing, and shipping.
Business Capabilities
├─ User Management → UserService
├─ Order Processing → OrderService
├─ Billing → BillingService
└─ Shipping → ShippingService
Teams own capabilities end-to-end
e.g.: Amazon teams for Cart, Search, Checkout
🏛️Decompose by Subdomain (DDD)DDD
Use Domain-Driven Design bounded contexts to create services with their own language and model.
DDD Subdomains
Core Domain → OrderService (competitive edge)
Supporting → InventoryService (needed but not core)
Generic → AuthService (buy/use off-shelf)
Each has its own model & language
e.g.: DDD by Eric Evans, Vaughn Vernon
🔄Strangler Fig Patternmigration
Incrementally extract services from a monolith while routing selected traffic to the new system.
Monolith → Microservices migration
Step 1: Monolith handles everything
Step 2: Extract UserService, route user traffic
Monolith → UserService
Step 3: Extract OrderService next
Step N: Monolith retires completely
e.g.: Real-world monolith to microservice migrations
📦Self-Contained Servicedesign
Design services to answer requests from local ownership data instead of chaining synchronous calls.
Anti-pattern (chatty):
OrderSvc → UserSvc → InventorySvc
all in one request = cascading failures
Self-Contained (correct):
OrderSvc → handles locally
syncs data async via events
e.g.: Event-driven microservices with local projections
02Communication Patterns- How services talk to each other
↩️Synchronous REST / gRPCsync
Direct request-response communication where the caller waits for a downstream service.
REST (HTTP/JSON)
ServiceA → GET /users/123 → UserService
← { id:123, name:"Alice" } ←
waits synchronously
gRPC (Protobuf / HTTP2)
ServiceA → GetUser(id:123) → UserService
← User{id,name} ←
strongly typed, faster than REST
e.g.: Express REST, gRPC with Protobuf, GraphQL
📨Asynchronous Messagingasync
Services communicate through a broker so producers and consumers can scale independently.
Message Broker Pattern
OrderSvc → publish(OrderPlaced) → [Broker]
↓ ↓
EmailSvc InventorySvc
processes processes
async async
Broker: Kafka, RabbitMQ, SQS, NATS
e.g.: Kafka, RabbitMQ, SQS, NATS
🔔Event-Driven Communicationevents
Services publish domain events when important business facts happen.
Domain Events
OrderService emits:
→ OrderPlaced { orderId, items, userId }
→ OrderCancelled { orderId, reason }
→ OrderShipped { orderId, trackingId }
Subscribers react:
EmailSvc listens → OrderPlaced
AnalyticsSvc listens → all events
InventorySvc listens → OrderPlaced, OrderCancelled
e.g.: Kafka events, EventBridge, Node EventEmitter
🌐API Gateway Patterngateway
A single entry point routes, authenticates, rate-limits, and protects backend services.
Request Flow through Gateway
Client → [API Gateway]
│ 1. Authenticate (JWT/OAuth)
│ 2. Rate limit check
│ 3. Route to service
│ 4. Load balance
↓
GET /users → UserService
POST /orders → OrderService
GET /products → ProductService
e.g.: Kong, AWS API Gateway, Nginx, Traefik
🔍Service Discoverydiscovery
Services register and discover dynamic endpoints instead of hardcoding hostnames or IPs.
Client-Side Discovery
ServiceA → query [Service Registry]
← "UserSvc is at 10.0.1.5:8080"
→ call 10.0.1.5:8080 directly
Server-Side Discovery
ServiceA → [Load Balancer]
LB queries registry internally
→ routes to correct instance
Registry: Consul, Eureka, K8s DNS
e.g.: Consul, Kubernetes DNS, Eureka
🛰️Microservices Communication Deep Divecommunication
Interactive deep dive on service discovery, load balancing, resilience, and live communication behavior.
Client -> Discovery -> Load Balancer -> Service Instance
Failures -> Retry / Circuit Breaker
Health checks -> dynamic routing
e.g.: Service discovery + round robin + circuit breaker simulation
03Service Design Patterns- How individual services are structured internally
🛸Sidecar Patterninfra
Run a helper container beside the app to handle cross-cutting infrastructure concerns.
Kubernetes Pod
┌─────────────────────────────────┐
│ Pod │
│ ┌────────────┐ ┌─────────────┐ │
│ │ Main App │ │ Sidecar │ │
│ │ :8080 │ │ Envoy Proxy│ │
│ │ │ │ Log Agent │ │
│ └────────────┘ └─────────────┘ │
│ shared network + storage │
└─────────────────────────────────┘
e.g.: Istio Envoy sidecar, Datadog agent, Fluentd
🏗️Backends for Frontends (BFF)design
Create a tailored backend/API layer per client type such as web, mobile, or TV.
Per-Client Backends
📱 Mobile → [BFF-Mobile] → lean payload
🌐 Web → [BFF-Web] → rich payload
📺 TV → [BFF-TV] → media-optimized
↓ all call same microservices
[UserSvc][OrderSvc][ProductSvc]
e.g.: Netflix, SoundCloud BFF architecture
🤝Ambassador Patternproxy
Use a local proxy to handle network concerns for a service.
Ambassador as Proxy
YourService → [Ambassador]
│ handles:
├─ retry logic
├─ circuit breaking
├─ request logging
├─ rate limiting
└─ TLS termination
↓
Remote Service / External API
e.g.: Envoy, Ambassador API Gateway, Linkerd
🕸️Service Meshinfra
A mesh of sidecar proxies manages service-to-service traffic transparently.
Service Mesh Topology
ServiceA ServiceB
[App] ←→ [Proxy] ←────→ [Proxy] ←→ [App]
↕ ↕
[Control Plane: Istio]
configures all proxies
handles: mTLS, tracing,
retries, load balance
e.g.: Istio, Linkerd, Consul Connect
🔄Anti-Corruption Layer (ACL)DDD
Translate between your clean domain model and an external or legacy model.
ACL protects your domain
External Legacy System
uses: customer_no, acct_ref
↓
[Anti-Corruption Layer]
translates: customer_no → userId
acct_ref → accountId
↓
Your Clean Domain
uses: userId, accountId
e.g.: Legacy adapters, SDK wrappers, domain mappers
04Data Patterns- How services manage and share data
🗄️Database per Servicedata
Each service owns its database and no other service reads or writes it directly.
Data Ownership Model
UserService → [PostgreSQL db_users]
OrderService → [MongoDB db_orders]
ProductService → [Redis db_products]
SearchService → [Elastic db_search]
✗ OrderService cannot query db_users directly
✓ OrderService calls UserService API instead
e.g.: Microservices data ownership best practice
✂️CQRSdata
Separate write models from read models so each can optimize for its own workload.
CQRS inside a service
WRITE SIDE (Commands)
POST /orders → CommandHandler
→ validates business rules
→ updates Write DB (normalized)
→ emits OrderPlaced event
READ SIDE (Queries)
GET /orders → QueryHandler
→ Read DB (denormalized, fast)
→ populated from events
e.g.: Event-sourced systems, denormalized read stores
📜Event Sourcingevents
Store every state change as an immutable event and rebuild state by replaying events.
Event Store (append-only log)
[1] AccountCreated { userId: 1, balance: 0 }
[2] MoneyDeposited { userId: 1, amount: 500 }
[3] MoneyWithdrawn { userId: 1, amount: 200 }
[4] MoneyDeposited { userId: 1, amount: 100 }
Replay 1→4: balance = 0+500-200+100 = 400
Time travel: replay 1→2 = balance = 500
e.g.: EventStoreDB, Axon, custom event logs
📤Transactional Outboxreliable events
Write business data and outgoing event records in one local database transaction.
Outbox Pattern Flow
Begin Transaction:
INSERT INTO orders (order data)
INSERT INTO outbox (event data) ← same tx
Commit Transaction ✓
[Outbox Poller / CDC]
reads outbox table
→ publishes to Kafka/RabbitMQ
→ marks outbox record as sent
Atomic: either both saved or neither
e.g.: Debezium outbox transform, custom outbox poller
🔀API Compositionquery
Aggregate data from multiple services into one response.
Composition Flow
Client: GET /order-summary/456
↓
[OrderComposer]
↓ parallel calls:
→ UserService.getUser(orderId.userId)
→ OrderService.getOrder(456)
→ ProductService.getProducts(orderItems)
← merge all responses
return combined OrderSummary to client
e.g.: GraphQL resolvers, BFF aggregators
👂Change Data Capture (CDC)CDC
Capture database changes and publish them as events.
CDC via DB Transaction Log
Application → writes to [PostgreSQL]
PostgreSQL → WAL (Write-Ahead Log)
[Debezium] → reads WAL changes
→ publishes to Kafka:
orders.created { ... }
orders.updated { ... }
Consumers → react to DB changes
e.g.: Debezium, Kafka Connect, database logs
05Reliability Patterns- Keep services resilient under failure
⚡Circuit Breakerresilience
Stop calling a failing dependency to prevent cascading failures.
Circuit Breaker State Machine
CLOSED (normal)
requests flow → 5 failures in 10s
↓
OPEN (tripped)
all requests → instant fail + fallback
wait 30s timeout
↓
HALF-OPEN (testing)
let 1 request through
success → back to CLOSED
fail → back to OPEN
e.g.: opossum, Resilience4j, Hystrix
🚢Bulkhead Patternisolation
Isolate resources so one failing area does not take down the whole system.
Resource Pools (Bulkheads)
Thread Pool A (10 threads) → Payment calls
Thread Pool B (10 threads) → Inventory calls
Thread Pool C (10 threads) → Email calls
Payment service hangs →
Pool A exhausted
Pool B, C still available
Inventory, Email still work ✓
e.g.: Thread pools, connection pools, K8s namespaces
🔁Retry with Exponential Backoffretry
Retry transient failures with progressively longer waits and jitter.
Retry Strategy
Attempt 1 → fails (wait 100ms)
Attempt 2 → fails (wait 200ms)
Attempt 3 → fails (wait 400ms)
Attempt 4 → success ✓
With Jitter (avoids thundering herd)
Wait = min(cap, base * 2^attempt) + random(0..100ms)
Idempotency required for safe retries!
e.g.: axios-retry, got retry, AWS SDK retry
⏱️Timeout Patterntimeout
Never wait forever for an outgoing call.
Timeout Configuration
connect_timeout: 2s (TCP handshake)
request_timeout: 5s (full response)
read_timeout: 3s (each read chunk)
ServiceA → calls ServiceB
→ no response in 5s
→ TimeoutException thrown
→ return fallback / 503
Without timeout: thread hangs forever
e.g.: fetch AbortController, axios timeout, gRPC deadline
🏃Health Check / Readiness Probeops
Expose endpoints that tell orchestrators whether the service is alive and ready.
Health Probe Types
Liveness: GET /health/live
Is the process alive? (not deadlocked?)
fail → K8s kills + restarts pod
Readiness: GET /health/ready
Is service ready to receive traffic?
fail → removed from load balancer
(e.g. still warming up DB connections)
Startup: GET /health/startup
Did the app finish starting? (slow start)
e.g.: Kubernetes livenessProbe, readinessProbe, Consul health
06Observability Patterns- See what happens inside distributed services
🔎Distributed Tracingobserve
Follow one request across services using trace IDs and spans.
Trace: traceId = abc-123
[Gateway] span 1: 0ms → 120ms
[UserSvc] span 2: 10ms → 40ms
[OrderSvc] span 3: 45ms → 110ms
[DB call] span 4: 50ms → 105ms ← slow!
[EmailSvc] span 5:115ms → 118ms
Identify bottleneck: DB call at span 4
e.g.: OpenTelemetry, Jaeger, Zipkin, AWS X-Ray
🪵Centralized Logginglogs
Aggregate structured logs from all services into one searchable place.
Log Aggregation Pipeline
ServiceA → { traceId, level, msg, ts }
ServiceB → { traceId, level, msg, ts }
ServiceC → { traceId, level, msg, ts }
↓ log shipper (Fluentd / Filebeat)
[Central Store: Elasticsearch / Loki]
↓
[Dashboard: Kibana / Grafana]
search: traceId=abc-123 → all logs
e.g.: ELK, Loki + Grafana, Datadog logs, CloudWatch
📊Metrics & Monitoringmetrics
Emit numeric service and resource measurements for dashboards and alerts.
RED Method (per service)
Rate → requests per second
Errors → error rate %
Duration → p50, p95, p99 latency
USE Method (per resource)
Utilization → CPU/Memory %
Saturation → queue depth
Errors → error count
e.g.: Prometheus + Grafana, Datadog, New Relic
🏷️Correlation IDobserve
Thread a unique request ID through headers, logs, and downstream calls.
Correlation ID Flow
Client → Gateway
generates: X-Request-ID: req-789xyz
passes header to all services
UserSvc: log { reqId: "req-789xyz", ... }
OrderSvc: log { reqId: "req-789xyz", ... }
PaymentSvc:log { reqId: "req-789xyz", ... }
Search logs: reqId=req-789xyz → full trace
e.g.: X-Request-ID, express-request-id, Morgan logger
🔍Log Aggregation + Alertingalerts
Trigger alerts from logs and metrics before users report problems.
Alert Rules (examples)
error_rate > 5% → PagerDuty alert
p99_latency > 2000ms → Slack warning
pod restarts > 3 → immediate page
disk usage > 85% → warning email
SLO / Error Budget
SLO: 99.9% uptime = 43.8 min/month
Budget: consumed 40 min this month
→ freeze deployments, focus on stability
e.g.: PagerDuty, OpsGenie, Grafana Alerts, CloudWatch Alarms
07Security Patterns- Secure service-to-service and client-to-service communication
🔒Mutual TLS (mTLS)security
Both client and server services verify each other with certificates.
mTLS Handshake
ServiceA → presents cert to ServiceB
ServiceB → presents cert to ServiceA
Both verify against trusted CA
Encrypted + mutually authenticated channel
Service Mesh handles this automatically
e.g.: Istio mTLS, Linkerd, SPIFFE/SPIRE
🎫Token-Based Auth (JWT)auth
Use signed tokens to propagate identity and authorization claims.
JWT Flow
Client → POST /auth/login
AuthSvc → signs JWT { userId, roles, exp }
Client → sends JWT in Authorization header
ServiceA → verify signature locally ✓
ServiceA → extract userId, roles from payload
Stateless — no session store needed
e.g.: jsonwebtoken, jose, Auth0, Keycloak, Cognito
🚫Zero Trust Architecturesecurity
Authenticate and authorize every request, even inside the private network.
Zero Trust per request
Old model: inside network = trusted
ServiceA calls ServiceB → just works
Zero Trust model: verify everything
ServiceA calls ServiceB
→ present identity (mTLS cert / JWT)
→ B verifies identity
→ B checks authorization policy
→ B logs the access
→ allow or deny
e.g.: BeyondCorp, SPIFFE/SPIRE, Istio AuthorizationPolicy
🔑Secrets Managementsecrets
Store and rotate credentials in a vault instead of hardcoding them.
Secrets Vault Pattern
✗ Bad: DB_PASS=secret123 in code / env
✓ Good: HashiCorp Vault
Service → authenticate to Vault
Vault → return secret (time-limited)
Service → use secret, auto-renew
Rotation: new secret → services pick up
automatically without redeploy
e.g.: HashiCorp Vault, AWS Secrets Manager, encrypted K8s Secrets
08Deployment Patterns- How microservices are deployed and released safely
🔵🟢Blue-Green Deploymentdeploy
Run two identical environments and switch traffic after the new one passes checks.
Blue [v1.0] ← 100% live traffic
Green [v2.0] ← deploy + test here
Switch: Blue → standby
Green → 100% live traffic
Rollback: flip switch back instantly
e.g.: AWS CodeDeploy, Kubernetes service switching
🐦Canary Deploymentdeploy
Release to a small percentage of traffic, monitor, then gradually increase.
100 users total:
5% → v2 (canary 🐦) — monitor closely
95% → v1 (stable)
metrics OK? → increase to 25% → 50% → 100%
metrics bad? → rollback 5% → 0% instantly
e.g.: Argo Rollouts, Flagger, Spinnaker, Istio weights
🔄Rolling Updatedeploy
Replace old instances with new instances gradually.
Rolling Update Progress
Start: [v1][v1][v1][v1][v1]
Step 1: [v2][v1][v1][v1][v1]
Step 2: [v2][v2][v1][v1][v1]
Step 3: [v2][v2][v2][v1][v1]
Done: [v2][v2][v2][v2][v2]
API must be backward-compatible!
e.g.: Kubernetes Deployment default rollout
👻Shadow / Mirror Deploymentdeploy
Mirror production traffic to a new version, but discard shadow responses.
Duplicate live traffic to new version silently
Users only receive response from old version
Compare latency, errors, and results of both versions
Best for: DB migrations, ML models, critical rewrites
e.g.: NGINX mirror module, Envoy traffic shadowing, Istio mirror
💥Recreate Deploymentdeploy
Stop old version first, then start the new version.
Terminate ALL current instances, then deploy new version
Guarantees no version mixing - clean state
Has intentional downtime window
Best for: dev/staging, breaking schema changes
e.g.: Kubernetes strategy: Recreate, controlled maintenance windows
⚖️A/B Testing Rolloutexperiment
Route different user segments to different versions to compare outcomes.
Route users by attributes (region, plan, ID)
Measure business outcomes: conversions, engagement, revenue
Not only release safety - this is product experimentation
Best for: feature flags, pricing tests, UX experiments
e.g.: LaunchDarkly, Statsig, Optimizely, custom feature-flag routers
🏗️Immutable Infrastructuredeploy
Never patch running instances; build a new image and replace them.
Mutable (old way)
Server → SSH in → apt update → patch
(drift: servers become snowflakes)
Immutable (correct)
Code change → build new Docker image
→ push to registry
→ deploy new pods
→ terminate old pods
Every deployment is predictable
e.g.: Docker, Kubernetes, Packer AMIs, GitOps with ArgoCD
🎯Deployment Interview Cardinterview
Layer-level interview focus across deployment strategies.
Q: Blue-Green vs Canary - when to choose each?
A: Blue-Green for instant rollback and strict cutover.
A: Canary for gradual risk control with live metrics.
Tip: mention rollback speed, observability, and infra cost tradeoffs.
09Distributed Transaction Patterns- How to maintain data consistency across services
⚗️Saga Pattern - Choreographytransactions
Services publish and react to events without a central coordinator.
Choreography Saga
OrderSvc → emit: OrderCreated
PaymentSvc → hear: OrderCreated
→ process payment
→ emit: PaymentProcessed
StockSvc → hear: PaymentProcessed
→ reserve stock
→ emit: StockReserved
ShipSvc → hear: StockReserved → ship
On failure: compensating events
PaymentSvc → emit: PaymentFailed
OrderSvc → hear: PaymentFailed → cancel order
e.g.: Kafka choreography, EventBridge rules
🎛️Saga Pattern - Orchestrationtransactions
A central orchestrator commands each service step and handles compensation.
Orchestration Saga
[Saga Orchestrator] drives the flow:
Step 1: call PaymentSvc.charge()
→ success → go to step 2
→ fail → compensate
Step 2: call StockSvc.reserve()
→ success → go to step 3
→ fail → call PaymentSvc.refund()
Step 3: call ShipSvc.schedule()
Full visibility: orchestrator knows state
e.g.: Temporal.io, AWS Step Functions, Conductor, Camunda
📤Outbox + Inbox Patternconsistency
Use outbox records for reliable sends and inbox records for idempotent receives.
Outbox (sender side)
BEGIN TX:
INSERT orders → order data
INSERT outbox → { msgId, event, status:pending }
COMMIT
Poller: read outbox → publish to Kafka → mark sent
Inbox (receiver side)
Receive event { msgId: "m-456" }
CHECK inbox table: msgId=m-456 exists?
→ YES: already processed, skip (idempotent)
→ NO: process + INSERT inbox(m-456)
e.g.: Debezium outbox, custom outbox poller, inbox table
🔒Two-Phase Commit (2PC)consistency
A coordinator asks participants to prepare, then commits or rolls back all participants.
2PC Protocol
Phase 1 — PREPARE:
Coordinator → "prepare?" → DB-1, DB-2, DB-3
DB-1 → "ready ✓"
DB-2 → "ready ✓"
DB-3 → "ready ✓"
Phase 2 — COMMIT:
Coordinator → "commit!" → all DBs
all commit atomically ✓
If DB-2 says "not ready":
Coordinator → "rollback!" → all DBs
e.g.: XA transactions; rarely preferred in microservices
Production microservices use patterns from many categories together: boundaries, communication, data ownership, failure handling, observability, security, release safety, and consistency all matter.