Cloud · Resilience · DWG NO. 027

Bulkhead

Split resources into isolated pools per dependency, so one overwhelmed dependency can't starve every other request.

TypeResilience
ScopeResource pools
ComplexityMedium
Common inConnection pools, thread pools, multi-tenant services

One slow dependency exhausts the shared pool everything else needs too

If every outgoing call — to the payments API, the recommendations service, the email provider — draws from one shared connection pool, a slow payments API can occupy every connection in that pool waiting on timeouts, leaving nothing available for the recommendations calls that were working fine.

Named ship compartments

Named after a ship's watertight compartments: partition the shared resource (connections, threads, queue capacity) into separate, fixed-size pools per dependency or per tenant. One pool flooding doesn't sink the others.

Payments pool(4 slots) — fullEmail pool(4 slots) — okRecs pool(4 slots) — okshared connection budget, partitioned

A fixed-size resource pool per dependency

Each dependency gets its own pool with a hard cap. Payments filling its four slots has no effect on the separate Email pool.

bulkhead-pool.js
class Bulkhead {
  #maxConcurrent;
  #active = 0;
  #queue = [];

  constructor(maxConcurrent) { this.#maxConcurrent = maxConcurrent; }

  async run(fn) {
    if (this.#active >= this.#maxConcurrent) {
      throw new Error("bulkhead full — rejecting immediately"); // fail fast, don't queue forever
    }
    this.#active++;
    try {
      return await fn();
    } finally {
      this.#active--;
    }
  }
}

const paymentsPool = new Bulkhead(2);
const emailPool = new Bulkhead(2);

const slowPaymentsCall = () => new Promise((r) => setTimeout(() => r("paid"), 5000));

paymentsPool.run(slowPaymentsCall);
paymentsPool.run(slowPaymentsCall);
paymentsPool.run(slowPaymentsCall).catch((e) => console.log(e.message)); // rejected — pool full

// Email pool is untouched by payments being saturated
emailPool.run(async () => "sent").then(console.log); // "sent"

Trade-offs