Microservices Architecture
Core Principles
Single Responsibility — each service owns one bounded context (e.g., Users, Orders, Inventory)
Decentralized data — each service has its own database; no shared DB between services
API contracts — services communicate via REST, gRPC, or message queues; never direct DB calls
Independent deployability — services deploy separately; CI/CD per service
Failure isolation — one service failing should not cascade (circuit breaker, bulkhead)
Communication Patterns
Synchronous (request/response):
REST over HTTP — simple, widely understood, good for queries
gRPC — binary protocol (protobuf), low latency, strongly typed
great for internal service-to-service calls
Asynchronous (event-driven):
Message queues — RabbitMQ, SQS, Kafka
producer emits event, consumer processes independently
decouples services, enables retry, replayability
When to use which:
Sync → when you need an immediate response (user login, read data)
Async → when result isn't needed immediately (send email, update analytics)
→ when you want to decouple producers from consumers
API Gateway:
Single entry point for clients
Handles auth, rate limiting, routing, aggregation
Tools: AWS API Gateway, Kong, Nginx, TraefikKey Patterns
// Saga Pattern — distributed transactions without 2PC
// Choreography: services react to events
// Orchestration: central coordinator (saga orchestrator)
// Example: Order saga (choreography)
// 1. OrderService emits OrderCreated
// 2. InventoryService listens, reserves stock → emits StockReserved
// 3. PaymentService listens, charges card → emits PaymentCharged
// 4. ShippingService listens, schedules delivery
// Compensating: if PaymentFailed → emit StockReleased
// Outbox Pattern — reliable event publishing
// Instead of calling message broker directly (which can fail after DB commit):
// 1. Write event to outbox table in SAME DB transaction as business data
// 2. Separate outbox poller reads events and publishes to broker
// Guarantees at-least-once delivery
// CQRS — Command Query Responsibility Segregation
// Write side: commands mutate state, emit events
// Read side: separate read model optimized for queries
// Often used with Event SourcingService Discovery & Configuration
# Docker Compose — local microservices setup
version: '3.9'
services:
api-gateway:
image: nginx
ports: ['80:80']
depends_on: [user-service, order-service]
user-service:
build: ./services/users
environment:
DATABASE_URL: postgres://user:pass@users-db:5432/users
RABBITMQ_URL: amqp://rabbitmq:5672
depends_on: [users-db, rabbitmq]
order-service:
build: ./services/orders
environment:
DATABASE_URL: postgres://user:pass@orders-db:5432/orders
USER_SERVICE_URL: http://user-service:3001
users-db:
image: postgres:16
volumes: [users-data:/var/lib/postgresql/data]
orders-db:
image: postgres:16
volumes: [orders-data:/var/lib/postgresql/data]
rabbitmq:
image: rabbitmq:3-management
ports: ['15672:15672'] # management UIKeep your own version of these notes — editable, searchable, and organised by your stack.
Start free