The name comes from ship compartments: a breach floods one section rather than the hull. Applied to a request path, it means each dependency gets a share of the workers and cannot exceed it.
// at most 4 of 12 workers may be waiting on payments
final class Bulkhead
{
public function run($key, $limit, callable $work)
{
$n = $this->redis->incr("inflight:{$key}");
$this->redis->expire("inflight:{$key}", 60);
try {
if ($n > $limit) { throw new TooBusy(); }
return $work();
} finally {
$this->redis->decr("inflight:{$key}");
}
}
}
The finally is load-bearing: a decrement missed on an exception leaks the counter until the expiry, and the bulkhead closes permanently. The expiry is the safety net for a worker killed outright. Choosing the limit is the hard part and there is no formula — start at a third of the pool for anything non-essential and watch how often it rejects.