Microservices
Decomposing systems into independently deployable services.
What Are Microservices?
Microservices architecture decomposes an application into small, independently deployable services, each owning its own data and business logic. Each service runs in its own process and communicates over the network.
Monolith vs Microservices
| Aspect | Monolith | Microservices |
|---|---|---|
| Deployment | Single unit | Independent per service |
| Scaling | Scale everything | Scale individual services |
| Data | Shared database | Database per service |
| Complexity | In the code | In the infrastructure |
| Team structure | One team, one codebase | Small teams per service |
Communication Patterns
Synchronous (Request-Response)
- REST/HTTP — simple, widely understood
- gRPC — binary protocol, strongly typed, efficient. Great for internal service-to-service
Asynchronous (Event-Driven)
- Message queues (RabbitMQ, SQS) — point-to-point delivery
- Event streams (Kafka) — publish-subscribe, event replay
Prefer async communication to reduce coupling and improve resilience.
Data Management
Each microservice owns its data store. This means:
- No shared databases — services can't query each other's tables
- Eventual consistency — data across services may be temporarily inconsistent
- Saga pattern — coordinate multi-service transactions through a sequence of local transactions with compensating actions
Service Discovery
Services need to find each other dynamically:
- Client-side discovery: client queries the registry, picks an instance (e.g., Netflix Eureka)
- Server-side discovery: a load balancer queries the registry (e.g., AWS ALB, Kubernetes Services)
Resilience Patterns
Circuit Breaker
Wraps calls to a service. If failures exceed a threshold, the circuit "opens" and fails fast instead of waiting for timeouts. After a cooldown, it allows a test request through.
Bulkhead
Isolates failures by partitioning resources. If one service's thread pool is exhausted, other services aren't affected. Named after ship bulkheads that contain flooding.
Retry with Backoff
Retry failed requests with exponentially increasing delays. Add jitter (randomness) to prevent thundering herd. Set a max retry count.
Migration: The Strangler Fig Pattern
Incrementally replace a monolith:
- Identify a bounded context to extract
- Build the new service alongside the monolith
- Route traffic to the new service via a facade/proxy
- Repeat until the monolith is fully replaced
This is safer than a big-bang rewrite and delivers value incrementally.