Back to Guides

Microservices Architecture Patterns

Design, build, and deploy microservices at scale with Kubernetes, Docker, and service mesh patterns.

25 min read
Expert LevelDistributed Systems

What You'll Learn

  • • Core microservices design patterns and principles
  • • Service decomposition strategies and domain boundaries
  • • API gateway patterns and inter-service communication
  • • Data consistency and distributed transaction patterns
  • • Kubernetes deployment and service mesh integration
  • • Monitoring, observability, and troubleshooting strategies

Introduction to Microservices Architecture

Microservices architecture decomposes applications into independent, loosely coupled services that communicate over well-defined APIs. This approach enables teams to develop, deploy, and scale services independently, resulting in improved agility, fault isolation, and technology diversity.

Core Principles

  • Single Responsibility: Each service focuses on a specific business capability
  • Decentralized: Services own their data and business logic
  • Fault Tolerant: Services handle failures gracefully without cascading
  • Observable: Comprehensive monitoring and logging across services

Service Decomposition Strategies

Domain-Driven Design (DDD) Approach

// Example: E-commerce domain boundaries
User Service:
  - User authentication and profiles
  - User preferences and settings

Product Catalog Service:
  - Product information and search
  - Inventory management

Order Service:
  - Order processing and workflow
  - Order history and tracking

Payment Service:
  - Payment processing
  - Transaction history

Notification Service:
  - Email and SMS notifications
  - Push notifications

Decomposition Patterns

By Business Capability

Organize services around business functions like user management, order processing, or inventory.

By Data Ownership

Each service owns its data and provides APIs for other services to access it.

Inter-Service Communication Patterns

Synchronous Communication

# API Gateway Configuration (Kubernetes Ingress)
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: api-gateway
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /$1
spec:
  rules:
  - host: api.example.com
    http:
      paths:
      - path: /users/(.*)
        pathType: Prefix
        backend:
          service:
            name: user-service
            port:
              number: 80
      - path: /orders/(.*)
        pathType: Prefix
        backend:
          service:
            name: order-service
            port:
              number: 80

Asynchronous Communication

# Event-Driven Architecture with Kafka
version: '3.8'
services:
  kafka:
    image: confluentinc/cp-kafka:latest
    environment:
      KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181
      KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://kafka:9092
      KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1
    
  order-service:
    image: order-service:latest
    environment:
      KAFKA_BROKERS: kafka:9092
      EVENT_TOPICS: order-created,order-updated,order-cancelled
    depends_on:
      - kafka
      
  notification-service:
    image: notification-service:latest
    environment:
      KAFKA_BROKERS: kafka:9092
      SUBSCRIBED_TOPICS: order-created,order-updated
    depends_on:
      - kafka

Data Management Patterns

Database per Service

Best Practice

Each microservice should have its own database to ensure loose coupling and independent evolution.

# Docker Compose with Separate Databases
version: '3.8'
services:
  user-service:
    image: user-service:latest
    environment:
      DB_HOST: user-db
      DB_NAME: users
    depends_on:
      - user-db
      
  user-db:
    image: postgres:15
    environment:
      POSTGRES_DB: users
      POSTGRES_USER: userservice
      POSTGRES_PASSWORD: userpass
    volumes:
      - user_data:/var/lib/postgresql/data

  order-service:
    image: order-service:latest
    environment:
      DB_HOST: order-db
      DB_NAME: orders
    depends_on:
      - order-db
      
  order-db:
    image: postgres:15
    environment:
      POSTGRES_DB: orders
      POSTGRES_USER: orderservice
      POSTGRES_PASSWORD: orderpass
    volumes:
      - order_data:/var/lib/postgresql/data

volumes:
  user_data:
  order_data:

Saga Pattern for Distributed Transactions

Handle distributed transactions using the Saga pattern, which manages data consistency across services through choreography or orchestration.

Kubernetes Deployment Patterns

Service Deployment

# Microservice Deployment
apiVersion: apps/v1
kind: Deployment
metadata:
  name: user-service
  labels:
    app: user-service
spec:
  replicas: 3
  selector:
    matchLabels:
      app: user-service
  template:
    metadata:
      labels:
        app: user-service
    spec:
      containers:
      - name: user-service
        image: user-service:v1.0.0
        ports:
        - containerPort: 8080
        env:
        - name: DB_HOST
          value: "user-db-service"
        - name: KAFKA_BROKERS
          value: "kafka-service:9092"
        resources:
          requests:
            memory: "256Mi"
            cpu: "250m"
          limits:
            memory: "512Mi"
            cpu: "500m"
        livenessProbe:
          httpGet:
            path: /health
            port: 8080
          initialDelaySeconds: 30
          periodSeconds: 10
        readinessProbe:
          httpGet:
            path: /ready
            port: 8080
          initialDelaySeconds: 5
          periodSeconds: 5

---
apiVersion: v1
kind: Service
metadata:
  name: user-service
spec:
  selector:
    app: user-service
  ports:
  - port: 80
    targetPort: 8080
  type: ClusterIP

Service Mesh with Istio

# Istio VirtualService for Traffic Management
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: user-service
spec:
  hosts:
  - user-service
  http:
  - match:
    - headers:
        version:
          exact: v2
    route:
    - destination:
        host: user-service
        subset: v2
      weight: 100
  - route:
    - destination:
        host: user-service
        subset: v1
      weight: 100

---
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: user-service
spec:
  host: user-service
  subsets:
  - name: v1
    labels:
      version: v1
  - name: v2
    labels:
      version: v2

Monitoring and Observability

The Three Pillars of Observability

Metrics

Prometheus + Grafana for collecting and visualizing performance metrics.

Logs

Centralized logging with ELK stack (Elasticsearch, Logstash, Kibana).

Traces

Distributed tracing with Jaeger or Zipkin for request flow analysis.

Prometheus Monitoring Setup

# Prometheus ConfigMap
apiVersion: v1
kind: ConfigMap
metadata:
  name: prometheus-config
data:
  prometheus.yml: |
    global:
      scrape_interval: 15s
    scrape_configs:
    - job_name: 'kubernetes-pods'
      kubernetes_sd_configs:
      - role: pod
      relabel_configs:
      - source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_scrape]
        action: keep
        regex: true
      - source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_path]
        action: replace
        target_label: __metrics_path__
        regex: (.+)

Production-Ready Configurations

Best Practices and Common Pitfalls

Best Practices

  • • Start with a monolith and decompose gradually
  • • Design for failure with circuit breakers and retries
  • • Implement comprehensive monitoring and alerting
  • • Use API versioning for backward compatibility
  • • Automate testing across service boundaries
  • • Implement proper security between services

Common Pitfalls to Avoid

  • • Creating too many services too early (nano-services)
  • • Sharing databases between services
  • • Synchronous communication everywhere
  • • Neglecting network latency and failure scenarios
  • • Inconsistent logging and monitoring
  • • Ignoring data consistency patterns