MicroservicePatterns.com
Resilience · Core

Bulkhead

The Bulkhead pattern partitions resources such as thread pools and connection pools per dependency or tenant, so a failure or overload in one part cannot exhaust resources for the rest.

Last updated

What is the Bulkhead pattern?

Named after the compartments in a ship's hull, a bulkhead partitions resources such as thread pools, connection pools, semaphores, queues or even instances per dependency, tenant or priority. When one partition is full, the others keep working.

What problem does the Bulkhead pattern solve?

If every call shares one pool, a single slow dependency can occupy all the threads or connections, and unrelated features fail along with it. Partitioning limits the damage to the feature that actually depends on the failing component.

How do you implement the Bulkhead pattern?

  1. Identify critical paths, non-critical paths and the dependencies each one uses.
  2. Give each its own pool or concurrency limit, sized from measurements.
  3. Reject new work quickly when a partition is full instead of queuing without limit.
  4. Combine it with timeouts and circuit breakers.
  5. Monitor saturation per bulkhead so you notice before users do.

When should you use it?

  • A service calls several dependencies that fail independently.
  • Some callers or tenants are noisy or less important than others.

When should you avoid it?

  • A service with one dependency and one workload, where there is nothing to isolate.

What do you gain?

  • Contains failures to one feature
  • Protects critical paths
  • Makes capacity planning explicit

What does it cost?

  • Resources can sit idle in a partition
  • More configuration to tune
  • Limits that are too low reject healthy traffic

What are common mistakes with the Bulkhead pattern?

  • Unbounded queues in front of the pool, which hide the problem until memory runs out.
  • Limits copied from a blog post instead of measured.

Bulkhead in practice

Illustrative scenario · fictional company

Marlow Market

Checkout and product reviews shared one HTTP client pool. When the third-party review provider hung, review calls used every connection and checkout calls waited behind them.

Each downstream dependency now has its own connection pool and concurrency limit. When the review provider hangs, only reviews fail.

Example decision record
Context
Checkout shares a connection pool with non-critical review and rating services.
Decision
Give each downstream dependency its own connection pool and concurrency limit.
Consequences
  • An outage in a non-critical dependency cannot starve checkout.
  • Pool saturation is monitored per dependency.