Skip to main content
โšก Calmops

Microservices Patterns 2026 Complete Guide: Architecture, Communication, and Data

Introduction

Microservices architecture has evolved significantly. In 2026, organizations have moved beyond initial adoption to refining their approaches, learning from production experiences, and establishing well-documented patterns. The focus has shifted from whether to use microservices to how to do it well.

This guide covers essential microservices patterns in 2026, from decomposition strategies to operational patterns. Whether you’re designing a new system or improving existing services, this guide provides practical insights.

Service Decomposition

When to Decompose

Good candidates for microservices:

  • Independent deployability requirements
  • Different scaling needs
  • Different team ownership domains
  • Technology heterogeneity needs
  • Business capability boundaries

Avoid for:

  • Simple applications
  • Tightly coupled business logic
  • Small teams
  • Performance-critical synchronous calls

Decomposition Strategies

# Kubernetes deployment for microservice
apiVersion: apps/v1
kind: Deployment
metadata:
  name: order-service
spec:
  replicas: 3
  selector:
    matchLabels:
      app: order-service
  template:
    metadata:
      labels:
        app: order-service
        version: v1
    spec:
      containers:
      - name: order-service
        image: myregistry/order-service:v1.2.3
        ports:
        - containerPort: 8080
        env:
        - name: DATABASE_URL
          valueFrom:
            secretKeyRef:
              name: db-credentials
              key: url
        resources:
          limits:
            memory: "512Mi"
            cpu: "500m"

Domain-Driven Design

// Bounded context - Order Service
namespace OrderDomain {
  interface Order {
    id: string;
    customerId: string;
    items: OrderItem[];
    status: OrderStatus;
    total: Money;
    createdAt: Date;
  }
  
  enum OrderStatus {
    PENDING = "PENDING",
    CONFIRMED = "CONFIRMED",
    SHIPPED = "SHIPPED",
    DELIVERED = "DELIVERED",
    CANCELLED = "CANCELLED"
  }
  
  interface OrderItem {
    productId: string;
    quantity: number;
    price: Money;
  }
  
  interface OrderService {
    createOrder(customerId: string, items: OrderItem[]): Promise<Order>;
    confirmOrder(orderId: string): Promise<Order>;
    cancelOrder(orderId: string): Promise<Order>;
    getOrder(orderId: string): Promise<Order>;
    getOrdersByCustomer(customerId: string): Promise<Order[]>;
  }
}

Communication Patterns

Synchronous Communication

// REST client
class OrderClient {
  private httpClient: AxiosInstance;
  
  async getOrder(orderId: string): Promise<Order> {
    const response = await this.httpClient.get(`/orders/${orderId}`);
    return response.data;
  }
  
  async createOrder(order: CreateOrderRequest): Promise<Order> {
    const response = await this.httpClient.post('/orders', order);
    return response.data;
  }
}

// gRPC service
syntax = "proto3";

package order;

service OrderService {
  rpc GetOrder(GetOrderRequest) returns (Order);
  rpc CreateOrder(CreateOrderRequest) returns (Order);
  rpc StreamOrders(StreamOrdersRequest) returns (stream Order);
}

message GetOrderRequest {
  string order_id = 1;
}

Asynchronous Communication

// Message publisher
class OrderEventPublisher {
  private publisher: KafkaProducer;
  
  async publishOrderCreated(order: Order): Promise<void> {
    const event = {
      type: 'ORDER_CREATED',
      payload: order,
      timestamp: new Date().toISOString(),
      correlationId: order.id
    };
    
    await this.publisher.send({
      topic: 'order-events',
      messages: [{
        key: order.id,
        value: JSON.stringify(event)
      }]
    });
  }
}

// Event consumer
class OrderEventHandler {
  @ProcessOrder('ORDER_CREATED')
  async handleOrderCreated(event: OrderEvent): Promise<void> {
    const order = event.payload;
    
    // Update analytics
    await this.analyticsService.trackOrder(order);
    
    // Send notification
    await this.notificationService.sendOrderConfirmation(order);
    
    // Reserve inventory
    await this.inventoryService.reserveItems(order.items);
  }
}

Service Mesh

# Istio virtual service - canary deployment
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  name: order-service
spec:
  hosts:
  - order-service
  http:
  - match:
    - headers:
        x-canary:
          exact: "true"
    route:
    - destination:
        host: order-service
        subset: v2
      weight: 100
  - route:
    - destination:
        host: order-service
        subset: v1
      weight: 100

API Gateway

Edge Layer

# Kong gateway configuration
_format_version: "3.0"

services:
  - name: order-service
    url: http://order-service:8080
    routes:
      - name: orders
        paths:
          - /api/orders
        methods:
          - GET
          - POST
        plugins:
          - name: rate-limiting
            config:
              minute: 100
              policy: redis
              redis_host: redis
          - name: cors
            config:
              origins:
                - "https://example.com"
              methods:
                - GET
                - POST
                - OPTIONS
              headers:
                - Authorization
                - Content-Type
          - name: jwt
            config:
              key_claim_name: kid

  - name: payment-service
    url: http://payment-service:8080
    routes:
      - name: payments
        paths:
          - /api/payments

plugins:
  - name: prometheus
    config:
      per_consumer: false

BFF Pattern

// Backend for Frontend
class MobileBFF {
  private orderClient: OrderClient;
  private userClient: UserClient;
  private inventoryClient: InventoryClient;
  
  async getHomeScreenData(userId: string): Promise<MobileHomeData> {
    // Fetch in parallel
    const [user, recentOrders, recommendations] = await Promise.all([
      this.userClient.getProfile(userId),
      this.orderClient.getRecentOrders(userId),
      this.inventoryClient.getRecommendations(userId)
    ]);
    
    return {
      user: {
        name: user.name,
        avatar: user.avatar
      },
      recentOrders: recentOrders.map(o => ({
        id: o.id,
        status: o.status,
        total: o.total
      })),
      recommendations: recommendations.slice(0, 10)
    };
  }
}

Data Management

Database per Service

// Each service owns its data
// Order Service Database (PostgreSQL)
class OrderRepository {
  async findById(id: string): Promise<Order | null> {
    return this.db.query(
      'SELECT * FROM orders WHERE id = $1',
      [id]
    ).then(r => r.rows[0]);
  }
}

// Inventory Service Database (MongoDB)
class InventoryRepository {
  async findByProductId(productId: string): Promise<Inventory> {
    return this.collection.findOne({ productId });
  }
}

CQRS Pattern

// Command side - write model
class OrderCommandHandler {
  async handleCreateOrder(cmd: CreateOrderCommand): Promise<Order> {
    // Validate
    const inventory = await this.inventoryQuery.getAvailable(cmd.items);
    if (!inventory.available) {
      throw new InsufficientInventoryError();
    }
    
    // Create order
    const order = new Order({
      ...cmd,
      status: OrderStatus.PENDING
    });
    
    await this.orderStore.save(order);
    
    // Publish event
    await this.eventBus.publish(new OrderCreatedEvent(order));
    
    return order;
  }
}

// Query side - read model
class OrderQueryHandler {
  async getOrderSummary(orderId: string): Promise<OrderSummary> {
    // Read from optimized read model
    return this.readModel.findById(orderId);
  }
  
  async getCustomerOrders(customerId: string): Promise<OrderSummary[]> {
    return this.readModel.findByCustomer(customerId);
  }
}

Saga Pattern

// Orchestration-based saga
class OrderSaga {
  async execute(order: CreateOrderCommand): Promise<Order> {
    try {
      // Step 1: Create order (pending)
      const order = await this.orderService.create(order);
      
      // Step 2: Reserve inventory
      await this.inventoryService.reserve(order.items);
      
      // Step 3: Process payment
      await this.paymentService.charge(order.customerId, order.total);
      
      // Step 4: Confirm order
      return await this.orderService.confirm(order.id);
      
    } catch (error) {
      // Compensating transactions
      await this.compensate(order);
      throw error;
    }
  }
  
  private async compensate(order: Order): Promise<void> {
    // Release inventory
    await this.inventoryService.release(order.items).catch(() => {});
    
    // Refund payment
    await this.paymentService.refund(order.id).catch(() => {});
    
    // Cancel order
    await this.orderService.cancel(order.id).catch(() => {});
  }
}

Service Discovery

Registration

// Service registration
class ServiceRegistry {
  async register(service: ServiceInstance): Promise<void> {
    await this.etcd.put(
      `/services/${service.name}/${service.id}`,
      JSON.stringify({
        ...service,
        registeredAt: new Date(),
        healthCheck: service.healthCheckUrl
      }),
      { ttl: 30 } // Heartbeat every 30 seconds
    );
  }
  
  async discover(serviceName: string): Promise<ServiceInstance[]> {
    const response = await this.etcd.getAll(
      `/services/${serviceName}/`
    );
    
    return response.kvs.map(kv => JSON.parse(kv.value.toString()));
  }
}

Load Balancing

// Client-side load balancing
class LoadBalancer {
  constructor(
    private serviceRegistry: ServiceRegistry,
    private strategy: LoadBalancingStrategy = new RoundRobinStrategy()
  ) {}
  
  async getService(serviceName: string): Promise<ServiceInstance> {
    const instances = await this.serviceRegistry.discover(serviceName);
    
    // Filter healthy instances
    const healthy = instances.filter(i => i.isHealthy());
    
    return this.strategy.select(healthy);
  }
}

// Client with ribbon
@FeignClient(name: 'order-service')
interface OrderClient {
  @GetMapping('/orders/{id}')
  getOrder(@PathVariable('id') id: string): Order;
}

Observability

Distributed Tracing

// OpenTelemetry instrumentation
import { trace, SpanStatusCode } from '@opentelemetry/api';

const tracer = trace.getTracer('order-service');

class OrderService {
  async createOrder(cmd: CreateOrderCommand): Promise<Order> {
    return tracer.startActiveSpan('createOrder', async (span) => {
      try {
        span.setAttribute('order.customerId', cmd.customerId);
        span.setAttribute('order.itemCount', cmd.items.length);
        
        // Validate
        span.addEvent('Validating order');
        await this.validator.validate(cmd);
        
        // Create
        span.addEvent('Creating order');
        const order = await this.repository.create(cmd);
        
        // Publish event
        span.addEvent('Publishing event');
        await this.eventBus.publish(new OrderCreated(order));
        
        span.setStatus({ code: SpanStatusCode.OK });
        return order;
        
      } catch (error) {
        span.setStatus({
          code: SpanStatusCode.ERROR,
          message: error.message
        });
        throw error;
      } finally {
        span.end();
      }
    });
  }
}

Health Checks

# Kubernetes health probes
apiVersion: v1
kind: Pod
metadata:
  name: order-service
spec:
  containers:
  - name: order-service
    image: order-service:latest
    livenessProbe:
      httpGet:
        path: /health/live
        port: 8080
      initialDelaySeconds: 10
      periodSeconds: 10
    readinessProbe:
      httpGet:
        path: /health/ready
        port: 8080
      initialDelaySeconds: 5
      periodSeconds: 5

External Resources

Documentation

Tools

Learning

Conclusion

Microservices patterns in 2026 are well-established. The key is understanding trade-offs and choosing patterns that fit your organization and requirements.

Start with clear domain boundaries. Use asynchronous communication where possible. Implement observability from day one. And remember: microservices are a means to an end, not a goal in themselves.

The best architecture is the one that enables your team to deliver value effectively. Choose wisely.

Comments