Microservices
02 / 02

Microservices Architecture

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, Traefik

Key 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 Sourcing

Service 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 UI

Keep your own version of these notes — editable, searchable, and organised by your stack.

Start free