Intermediate12 min

Bulkhead

Isolate resources so one overloaded dependency can't sink the whole ship.

By the end of this lesson, partition resource pools so a failure in one area can't starve the others.

How deep?
How the pieces actually move.

Named after a ship's watertight compartments: if one floods, the others keep the ship afloat. A bulkhead partitions resources — separate thread pools, connection pools, or instances per dependency or tenant — so that saturating one partition can't consume the resources the others need.

First, the whole system

First, see the whole system. Then we’ll open it up.

Isolated pools

Isolated pools

  1. Each dependency gets its own pool; a slow Dependency A drains only Pool A, leaving B unaffected.
flowchart TB
  req[Requests] --> pa[Pool A -> Dependency A]
  req --> pb[Pool B -> Dependency B]
  pa -.slow.-> pa
  pb --> ok[B unaffected]
Why it exists

You know what happens. Now see why it works.

It stops the exact mechanism behind cascading failure: shared resource exhaustion. If every outbound call shares one thread pool, one slow dependency drains it and everything fails together. Per-dependency bulkheads confine that damage.

Cost

Isolation costs efficiency: dedicated pools can't share spare capacity, so you provision more headroom overall. You trade some utilization for the guarantee that one failure stays contained.

Why isolate pools per dependency instead of sharing one big pool?

A shared pool lets one slow dependency drain everything; isolated pools confine exhaustion to the failing dependency.

Bulkheads cap how much load a component absorbs. When it hits that cap, how should it push back on its callers?

Next: Backpressure →