On this page
Microservices Overview
Microservices is an architectural style that structures an application as a collection of loosely coupled, independently deployable services organized around business capabilities.
Monolith vs Microservices
Monolith: Microservices:
┌─────────────────────┐ ┌──────┐ ┌──────┐ ┌──────┐
│ User │ Order │ Pay │ │ User │ │Order │ │ Pay │
│ Module│Module│Module│ │ Svc │ │ Svc │ │ Svc │
└─────────────────────┘ └──┬───┘ └──┬───┘ └──┬───┘
Single deployment Independent deployments
| Aspect | Monolith | Microservices |
|---|---|---|
| Deployment | All-or-nothing | Independent |
| Scaling | Scale entire app | Scale individual services |
| Technology | Single stack | Polyglot possible |
| Complexity | Lower (initially) | Higher (distributed) |
| Team structure | Single team | Team per service |
| Data | Shared database | Database per service |
Key Principles
- Single responsibility — each service owns one business domain
- Decentralized data — each service has its own database
- Independent deployment — deploy without affecting others
- Failure isolation — one service failure doesn’t cascade
- Design for failure — circuit breakers, retries, fallbacks
When to Use Microservices
Good fit:
- Large team (Conway’s Law — architecture mirrors org structure)
- Different scaling requirements per domain
- Need for independent deployment cycles
- Polyglot requirements (different languages per service)
Poor fit:
- Small team (< 10 developers)
- Simple domain with low traffic
- Early-stage startup (premature decomposition)
- Strong transactional requirements across domains
Service Boundaries
Define by business capability, not technical layer:
Good: Bad:
User Service Controller Service
Order Service Service Layer Service
Payment Service Repository Service
Inventory Service Database Service
Use Domain-Driven Design (DDD) bounded contexts to identify boundaries.
Infrastructure Components
┌─────────────┐
│ API Gateway │
└──────┬──────┘
┌───────────────┼───────────────┐
▼ ▼ ▼
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ User Svc │ │ Order Svc │ │ Product Svc │
└──────┬──────┘ └──────┬──────┘ └──────┬──────┘
│ │ │
┌──────┴──────┐ ┌──────┴──────┐ ┌──────┴──────┐
│ User DB │ │ Order DB │ │ Product DB │
└─────────────┘ └─────────────┘ └─────────────┘
Supporting: Service Discovery, Config Server, Message Broker,
Distributed Tracing, Centralized Logging
Challenges
| Challenge | Solution |
|---|---|
| Distributed transactions | Saga pattern, eventual consistency |
| Service discovery | Eureka, Consul, Kubernetes DNS |
| Configuration | Spring Cloud Config, etcd |
| Monitoring | Prometheus, Grafana, Zipkin |
| Data consistency | Event sourcing, CQRS |
| Network latency | Caching, async messaging |
| Testing | Contract testing (Pact), test containers |
Migration Strategy
Don’t rewrite — evolve gradually:
- Strangler Fig — new features as microservices, old code remains
- Extract service — pull one module out of monolith
- Branch by abstraction — interface in monolith, implementation in new service
- Database first — separate schemas before separating services
Best Practices
- Start with a modular monolith — extract services when boundaries are clear
- Invest in observability from day one (logging, metrics, tracing)
- Automate everything — CI/CD, testing, deployment
- Design for failure — assume network calls will fail
- Keep services small but not too small (avoid nanoservices)