Microservices Design Patterns
A comprehensive guide to essential design patterns for building robust microservices architectures.
Communication Patterns
1. API Gateway Pattern
Central entry point for all client requests.
ββββββββββββββ βββββββββββββββ ββββββββββββββββ
β Client ββββββΆβ API Gateway ββββββΆβ Services β
ββββββββββββββ βββββββββββββββ ββββββββββββββββ
Responsibilities:
- Request routing
- Rate limiting
- Authentication/Authorization
- Load balancing
- Response aggregation
Implementation (ASP.NET Core + Ocelot):
// ocelot.json
{
"Routes": [
{
"DownstreamPathTemplate": "/api/orders/{everything}",
"DownstreamScheme": "https",
"DownstreamHostAndPorts": [{ "Host": "orders-service", "Port": 443 }],
"UpstreamPathTemplate": "/orders/{everything}",
"UpstreamHttpMethod": [ "GET", "POST", "PUT" ]
}
]
}
2. Service Discovery
Dynamic service location without hardcoded addresses.
Client-Side Discovery:
// Using Consul
var services = await _consul.Health.Service("order-service", passing: true);
var selectedService = LoadBalance(services);
Server-Side Discovery:
- Load balancer queries service registry
- Kubernetes built-in DNS
3. Circuit Breaker
Prevent cascade failures when services are unavailable.
// Using Polly
var circuitBreaker = Policy
.Handle<HttpRequestException>()
.CircuitBreakerAsync(
exceptionsAllowedBeforeBreaking: 3,
durationOfBreak: TimeSpan.FromSeconds(30),
onBreak: (ex, duration) => _logger.LogWarning("Circuit open"),
onReset: () => _logger.LogInformation("Circuit closed")
);
States:
- Closed: Normal operation
- Open: Requests fail immediately
- Half-Open: Testing if service recovered
Data Management Patterns
4. Database per Service
Each service owns its data store.
βββββββββββββββ βββββββββββββββ βββββββββββββββ
β Order Svc β β User Svc β β Product Svc β
ββββββββ¬βββββββ ββββββββ¬βββββββ ββββββββ¬βββββββ
β β β
ββββββββΌβββββββ ββββββββΌβββββββ ββββββββΌβββββββ
β Orders DB β β Users DB β β Products DB β
β (SQL) β β (Postgres) β β (MongoDB) β
βββββββββββββββ βββββββββββββββ βββββββββββββββ
Benefits:
- Loose coupling
- Independent scaling
- Technology freedom
- Data isolation
5. Saga Pattern
Distributed transactions across services.
Choreography (Event-driven):
public class OrderCreatedHandler : IHandleMessages<OrderCreated>
{
public async Task Handle(OrderCreated message)
{
var result = await _inventory.ReserveStock(message.Items);
if (result.Success)
await _bus.Publish(new StockReserved { OrderId = message.OrderId });
else
await _bus.Publish(new OrderCancelled { OrderId = message.OrderId });
}
}
Orchestration (Central coordinator):
public class CreateOrderSaga : Saga<CreateOrderSagaData>
{
public async Task Start(CreateOrder command)
{
await RequestTimeout<OrderTimeout>(TimeSpan.FromMinutes(5));
await _inventory.ReserveStock(command);
}
public async Task Handle(StockReserved message)
{
await _payment.ProcessPayment(Data.OrderId);
}
public async Task Handle(PaymentProcessed message)
{
await _shipping.CreateShipment(Data.OrderId);
MarkAsComplete();
}
}
6. CQRS (Command Query Responsibility Segregation)
Separate read and write models.
Commands Queries
β β
βΌ βΌ
ββββββββββββββββββ ββββββββββββββββββ
β Write Model ββββeventsβββΆβ Read Model β
β (Normalized) β β (Denormalized) β
ββββββββββ¬ββββββββ βββββββββ¬βββββββββ
β β
ββββββββββΌββββββββ βββββββββΌβββββββββ
β Write DB β β Read DB β
β (PostgreSQL) β β (ElasticSearch)β
ββββββββββββββββββ ββββββββββββββββββ
7. Event Sourcing
Store state as sequence of events.
public class Order : AggregateRoot
{
public void CreateOrder(CreateOrderCommand cmd)
{
Apply(new OrderCreated { OrderId = cmd.OrderId });
}
public void AddItem(AddItemCommand cmd)
{
Apply(new ItemAdded { ProductId = cmd.ProductId, Quantity = cmd.Quantity });
}
private void On(OrderCreated e) => Id = e.OrderId;
private void On(ItemAdded e) => Items.Add(new OrderItem(e.ProductId, e.Quantity));
}
Resilience Patterns
8. Retry Pattern
Automatic retry with backoff.
var retryPolicy = Policy
.Handle<HttpRequestException>()
.WaitAndRetryAsync(
retryCount: 3,
sleepDurationProvider: attempt =>
TimeSpan.FromSeconds(Math.Pow(2, attempt))
);
9. Bulkhead Pattern
Isolate resources to prevent cascade failures.
var bulkhead = Policy.BulkheadAsync(
maxParallelization: 10,
maxQueuingActions: 20
);
// Each service has isolated thread pool
var orderBulkhead = CreateBulkhead("orders", 10);
var paymentBulkhead = CreateBulkhead("payments", 5);
10. Sidecar Pattern
Deploy helper components alongside services.
# Kubernetes Pod with Sidecar
spec:
containers:
- name: main-app
image: my-service:latest
- name: logging-sidecar
image: fluentd:latest
- name: proxy-sidecar
image: envoy:latest
Deployment Patterns
11. Blue-Green Deployment
Zero-downtime releases.
βββββββββββββββββββ
β Load Balancer β
ββββββββββ¬βββββββββ
β
ββββββ΄βββββ
β β
βΌ βΌ
βββββββββ βββββββββ
β Blue β β Green β
β (v1) β β (v2) β β New version
β ACTIVEβ β IDLE β
βββββββββ βββββββββ
12. Canary Deployment
Gradual traffic shift to new version.
// Traffic routing example
public IEndpoint RouteRequest(string userId)
{
var hash = ComputeHash(userId);
if (hash % 100 < 5) // 5% to canary
return _canaryEndpoint;
return _stableEndpoint;
}
Observability Patterns
13. Distributed Tracing
Track requests across services.
// Using OpenTelemetry
using var activity = ActivitySource.StartActivity("ProcessOrder");
activity?.SetTag("order.id", orderId);
await _httpClient.PostAsync(url, content); // Automatically propagates trace context
14. Log Aggregation
Centralized logging from all services.
{
"timestamp": "2024-01-15T10:30:00Z",
"service": "order-service",
"traceId": "abc123",
"spanId": "def456",
"level": "INFO",
"message": "Order created",
"orderId": "ORD-001"
}
15. Health Check Pattern
Monitor service health.
public class DatabaseHealthCheck : IHealthCheck
{
public async Task<HealthCheckResult> CheckHealthAsync(
HealthCheckContext context,
CancellationToken cancellationToken)
{
try
{
await _db.ExecuteAsync("SELECT 1");
return HealthCheckResult.Healthy();
}
catch (Exception ex)
{
return HealthCheckResult.Unhealthy("Database unavailable", ex);
}
}
}
Pattern Selection Guide
| Scenario | Recommended Pattern |
|---|---|
| Cross-service transactions | Saga |
| High read/write ratio | CQRS |
| Audit requirements | Event Sourcing |
| Service unavailability | Circuit Breaker |
| Network instability | Retry + Timeout |
| Resource isolation | Bulkhead |
| Zero-downtime deploy | Blue-Green |
| Risk mitigation | Canary |
Sources
Arhitectura/microservices design patterns.png