Contents

Bulkhead Pattern

Bulkhead Pattern

It isolates different parts of a system so that failure in one component does not affect others. Each service or group of services operates in its own compartment,” similar to ship bulkheads.

  • Improves system resilience by containing failures within a single service or module.
  • Ensures stability in applications like streaming platforms, where a failure in recommendations won’t affect video playback or user management.

Implementation:

  1. Semaphore Bulkhead (Lightweight): Limits the number of concurrent calls using a simple counter (Semaphore).
  • Behavior: The calling thread is blocked until a permit is available.
  • Best for: High-throughput, low-latency calls where you don’t want the overhead of managing extra thread pools.
  1. Thread Pool Bulkhead (Heavy Isolation): Uses a dedicated thread pool and a waiting queue for the service.
  • Behavior: The calling thread is released immediately (Asynchronous), and the task is handed off to a specific pool.
  • Best for: Calls to slow, unreliable external services where you want to ensure they never occupy your main application threads.

Java example spring boot with Resilience4j

Configuration (application.yml)

resilience4j:
  bulkhead:
    instances:
      orderService:
        maxConcurrentCalls: 10          # Only 10 threads can call this at once
        maxWaitDuration: 500ms          # Wait 0.5s for a spot before failing
  thread-pool-bulkhead:
    instances:
      paymentService:
        maxThreadPoolSize: 5            # Dedicated small pool for payments
        coreThreadPoolSize: 2
        queueCapacity: 10

Implementation

@Service
public class CheckoutService {

    // Standard Semaphore Bulkhead
    @Bulkhead(name = "orderService", fallbackMethod = "bulkheadFallback")
    public String processOrder() {
        return "Order Processed";
    }

    // Thread Pool Bulkhead (Returns a CompletionStage/Future)
    @Bulkhead(name = "paymentService", type = Bulkhead.Type.THREADPOOL)
    public CompletableFuture<String> processPayment() {
        return CompletableFuture.completedFuture("Payment Processed");
    }

    public String bulkheadFallback(BulkheadFullException ex) {
        return "System is at capacity. Please try again later.";
    }
}

Bulkhead vs. Circuit Breaker

PatternGoalAnalogy
Circuit BreakerStop calling a failing service to give it time to recover.An electrical fuse that trips to stop the flow.
BulkheadLimit the resources consumed by a service so others aren’t affected.Watertight compartments in a ship’s hull.
Info
Use bulkheads to protect your “Golden Path.”. Example: You have one thread pool for User Login (Critical) and a separate, smaller bulkhead for Product Recommendations (Non-critical). If the recommendation engine slows down, it will fill its small pool and start failing fast, but it will never prevent a user from logging in.