Microservices Patterns¶
What are Microservices?¶
Architectural style where application is composed of small, independent services that communicate over well-defined APIs.
Service Decomposition¶
Decomposition Strategies¶
Communication Patterns¶
Synchronous Communication¶
Asynchronous Communication¶
API Gateway Pattern¶
Backend for Frontend (BFF)¶
Service Discovery¶
Client-Side Discovery¶
Server-Side Discovery¶
Circuit Breaker Pattern¶
Prevents cascading failures by failing fast when a service is unavailable.
// Resilience4j example
@CircuitBreaker(name = "paymentService", fallbackMethod = "paymentFallback")
public PaymentResponse processPayment(PaymentRequest request) {
return paymentClient.charge(request);
}
public PaymentResponse paymentFallback(PaymentRequest request, Exception e) {
// Queue for retry, return cached response, or degrade gracefully
return PaymentResponse.pending("Payment queued for processing");
}
// Configuration
resilience4j.circuitbreaker:
instances:
paymentService:
failureRateThreshold: 50 # Open at 50% failure rate
waitDurationInOpenState: 60000 # 60s before half-open
permittedNumberOfCallsInHalfOpenState: 3
slidingWindowSize: 10
Bulkhead Pattern¶
Isolates failures to prevent resource exhaustion.
// Thread pool bulkhead
@Bulkhead(name = "paymentService", type = Bulkhead.Type.THREADPOOL)
public PaymentResponse processPayment(PaymentRequest request) {
return paymentClient.charge(request);
}
// Semaphore bulkhead (limits concurrent calls)
@Bulkhead(name = "inventoryService", type = Bulkhead.Type.SEMAPHORE)
public InventoryResponse checkInventory(String productId) {
return inventoryClient.check(productId);
}
// Configuration
resilience4j.bulkhead:
instances:
paymentService:
maxConcurrentCalls: 10
maxWaitDuration: 500ms
Saga Pattern¶
Manages distributed transactions across services.
Choreography (Event-Based)¶
Orchestration (Central Coordinator)¶
// Orchestration example
public class OrderSagaOrchestrator {
public void createOrder(CreateOrderCommand command) {
try {
// Step 1: Create order
Order order = orderService.create(command);
// Step 2: Reserve inventory
inventoryService.reserve(order.getItems());
// Step 3: Process payment
paymentService.charge(order.getPayment());
// Step 4: Confirm order
orderService.confirm(order.getId());
} catch (InventoryException e) {
orderService.cancel(order.getId());
throw e;
} catch (PaymentException e) {
inventoryService.release(order.getItems());
orderService.cancel(order.getId());
throw e;
}
}
}
Sidecar Pattern¶
Deploy helper components alongside main service.
Service Mesh¶
Infrastructure layer for service-to-service communication.
Strangler Fig Pattern¶
Incrementally migrate from monolith to microservices.
Data Patterns¶
Database per Service¶
API Composition¶
// Aggregate data from multiple services
@RestController
public class OrderDetailsController {
@GetMapping("/order-details/{orderId}")
public OrderDetails getOrderDetails(@PathVariable String orderId) {
// Parallel calls to services
CompletableFuture<Order> orderFuture =
CompletableFuture.supplyAsync(() -> orderService.getOrder(orderId));
CompletableFuture<Customer> customerFuture =
orderFuture.thenCompose(order ->
CompletableFuture.supplyAsync(() ->
customerService.getCustomer(order.getCustomerId())));
CompletableFuture<List<Product>> productsFuture =
orderFuture.thenCompose(order ->
CompletableFuture.supplyAsync(() ->
productService.getProducts(order.getProductIds())));
// Combine results
return CompletableFuture.allOf(orderFuture, customerFuture, productsFuture)
.thenApply(v -> new OrderDetails(
orderFuture.join(),
customerFuture.join(),
productsFuture.join()
)).join();
}
}
Common Interview Questions¶
- How do you handle distributed transactions?
- Saga pattern (choreography or orchestration)
-
Avoid 2PC, embrace eventual consistency
-
How do you prevent cascading failures?
-
Circuit breaker, bulkhead, timeouts, retries with backoff
-
Sync vs async communication?
- Sync: Simple, immediate response, tight coupling
-
Async: Loose coupling, resilient, complex
-
How to decompose a monolith?
- Strangler fig pattern
- Start with bounded contexts
-
Extract by business capability
-
Service discovery approaches?
- Client-side: Eureka, Consul
- Server-side: Kubernetes, load balancers