Skip to main content

Microservices

One-line summary: Microservices split a system into small, independently deployable services aligned to business capabilities โ€” trading operational complexity for team autonomy and independent scaling.


๐Ÿงฉ Core Conceptsโ€‹

Monolith vs. Microservicesโ€‹

flowchart TB
subgraph Monolith
M[Single Deployable<br/>UI + Orders + Payments + Users]
M --> MDB[(Shared DB)]
end
subgraph Microservices
GW[API Gateway]
GW --> S1[Orders Svc] --> D1[(Orders DB)]
GW --> S2[Payments Svc] --> D2[(Payments DB)]
GW --> S3[Users Svc] --> D3[(Users DB)]
end
AspectMonolithMicroservices
DeploymentOne unitIndependent per service
ScalingWhole app togetherPer-service, targeted
Tech stackUniformPolyglot allowed
Team autonomyCoupledHigh (own service end-to-end)
DataShared DB, easy joins/txnsDB-per-service, distributed data
Operational costLowHigh (infra, observability, networking)
Fault isolationWeak (one bug can crash all)Strong (blast radius contained)
Local dev/debugSimpleComplex (many moving parts)

Start with a well-structured monolith; extract services when team size, scaling needs, or deployment friction justify the added complexity.

Service Boundaries & DDDโ€‹

Use Domain-Driven Design to draw boundaries. Each service should own a bounded context โ€” a cohesive business capability with its own data. Aim for high cohesion inside a service and loose coupling between services. Avoid the distributed monolith anti-pattern (services that must deploy together).

Service Discoveryโ€‹

Instances come and go (autoscaling, failures), so their network locations are dynamic. A service registry tracks healthy instances.

flowchart LR
S[Service Instance] -->|register / heartbeat| R[(Service Registry)]
C[Caller] -->|lookup 'orders'| R
R -->|healthy instances| C
C --> S
  • Client-side discovery โ€” caller queries the registry and load-balances itself.
  • Server-side discovery โ€” a load balancer / gateway resolves the target (e.g., Kubernetes Services, Consul, Eureka).

API Gatewayโ€‹

A single entry point for clients that handles cross-cutting concerns so individual services don't have to:

  • Routing & request aggregation
  • Authentication / authorization
  • Rate limiting & throttling
  • TLS termination, caching, request/response transformation

See API Design for the contract details behind the gateway.

Inter-Service Communication: Sync vs. Asyncโ€‹

flowchart LR
subgraph Sync[Synchronous]
A[Order Svc] -->|REST/gRPC request| B[Payment Svc]
B -->|response| A
end
subgraph Async[Asynchronous]
C[Order Svc] -->|publish event| Q[(Broker)]
Q --> D[Payment Svc]
Q --> E[Notification Svc]
end
Synchronous (REST/gRPC)Asynchronous (events/queues)
CouplingTemporal (both must be up)Decoupled
LatencyImmediate responseEventual
Failure impactCascades if downstream slowAbsorbed by broker
Best forQuery needing an answer nowFire-and-forget, fan-out, workflows

Prefer async messaging for workflows and fan-out (see Message Queues); use sync when the caller genuinely needs an immediate result.


๐Ÿ”„ Saga Pattern (Distributed Transactions)โ€‹

Without a shared database you can't use a single ACID transaction across services. A saga is a sequence of local transactions; if one step fails, compensating transactions undo the prior steps.

sequenceDiagram
participant O as Order
participant P as Payment
participant I as Inventory
O->>O: create order (pending)
O->>P: charge customer
P-->>O: charged
O->>I: reserve stock
I-->>O: out of stock (fail)
O->>P: refund (compensate)
O->>O: cancel order
  • Choreography โ€” services react to each other's events; no central coordinator. Simple but harder to trace.
  • Orchestration โ€” a central orchestrator drives the steps and compensations. Clearer control flow, single point to reason about.

Sagas provide eventual consistency rather than immediate atomicity โ€” see Consistency Models.


๐Ÿ”Ž Observabilityโ€‹

With many services, you can't debug by reading one log file. The three pillars:

  • Logging โ€” structured, centralized logs correlated by a trace/correlation ID.
  • Metrics โ€” numeric time series (latency, error rate, throughput, saturation โ€” the RED/USE methods).
  • Tracing โ€” distributed traces follow a request across service hops to pinpoint bottlenecks.
flowchart LR
Svc1 --> Col[Telemetry Collector]
Svc2 --> Col
Svc3 --> Col
Col --> Logs[(Logs)]
Col --> Metrics[(Metrics)]
Col --> Traces[(Traces)]
Logs & Metrics & Traces --> Dash[Dashboards & Alerts]

๐Ÿ›ก๏ธ Resilience Patternsโ€‹

PatternProblem it solvesHow
TimeoutsHanging calls tie up resourcesCap how long a call may wait
Retries (+ backoff + jitter)Transient failuresRetry idempotent calls with exponential backoff
Circuit breakerCascading failures to a sick serviceTrip open after N failures, fail fast, probe to recover
BulkheadOne dependency exhausting all resourcesIsolate pools per dependency
FallbackDegrade gracefullyServe cached/default response
stateDiagram-v2
[*] --> Closed
Closed --> Open: failures >= threshold
Open --> HalfOpen: after cooldown
HalfOpen --> Closed: probe succeeds
HalfOpen --> Open: probe fails

Combine retries with idempotency (see API Design) to avoid duplicate side effects.


โš–๏ธ Trade-offs / When to Useโ€‹

Adopt microservices when...Stay monolithic when...
Multiple teams need to ship independentlySmall team / early-stage product
Components have very different scaling needsDomain is not yet well understood
You need fault isolation and polyglot stacksOperational maturity (CI/CD, observability) is low
Deployment of the monolith is a bottleneckSimplicity and low latency joins matter most

Prerequisites: strong automation (CI/CD), containerization/orchestration, centralized observability, and clear ownership โ€” without these, microservices amplify pain.


Note (AI-assisted draft): The following Interview Questions, Production Checklist, and Testing & Monitoring items are a draft. Add organization-specific CI/CD links and observability dashboards as needed.

Interview Questions (expanded answers)โ€‹

How do you decide whether to extract a component from the monolith into a microservice?โ€‹

Decision factors:

  • Business ownership: separate teams owning a capability is a strong signal.
  • Scaling needs: if a component needs a different scaling profile (e.g., CPU-heavy vs I/O-light), separate it.
  • Release cadence: independent deploy cycles argue for service extraction.
  • Operational readiness: ensure CI/CD, observability, and incident processes exist before extracting.

If costs (operational overhead, network latency, distributed testing) exceed benefits, delay extraction or consider modular monolith patterns.

Compare choreography vs orchestration for sagas โ€” when is each preferable?โ€‹

  • Choreography (event-driven): services publish events and react. Prefer when flows are naturally decoupled, event volume is manageable, and eventual consistency is acceptable. Pros: no single coordinator, easier horizontal scale. Cons: harder to debug and reason about end-to-end.

  • Orchestration (central controller): a saga orchestrator issues commands and tracks progress. Prefer when the sequence must be controlled, error handling needs centralized visibility, or business processes require strict ordering. Pros: clearer flow and observability. Cons: central point to scale/maintain.

How do you design service boundaries to minimize cross-service transactions and latency?โ€‹

  • Model around bounded contexts: group data and operations that are touched together.
  • Co-locate frequently-used data; denormalize when read latency dominates and you can tolerate eventual consistency.
  • Favor asynchronous messaging for long-running tasks and use request/response only where immediate answers are necessary.
  • Instrument and set SLAs for inter-service calls; identify hotspots and consider API gateway-level aggregation.

Production Checklistโ€‹

  • Ensure CI/CD pipelines for each service and a global integration test workflow
  • Centralize observability (traces, metrics, logs) and enforce structured logs with correlation IDs
  • Harden network policies, mTLS, and service-to-service auth (e.g., SPIFFE/SPIRE)
  • Automate schema and contract migrations with consumer-driven contract tests
  • Maintain a shared dashboard with SLOs and error budgets per service

Testing & Monitoringโ€‹

  • Run integration tests that validate sagas and compensations end-to-end
  • Simulate partial failures and validate circuit breakers and bulkheads behave correctly
  • Measure cross-service latency and set SLOs per interaction
  • Validate tracing propagation (trace IDs) across service boundaries under load

โ† Back to System Design ยท ยฉ sparshjaswal