The bulkhead pattern isolates parts of a system into separate pools, such as a connection pool per dependency or an instance group per tenant, so that a failure or overload in one pool does not spread. It limits blast radius for both outages and some security incidents.
The idea in one picture
A ship's hull is split into sections. If one section floods, the others stay dry. Microsoft's Azure Architecture Center uses that analogy for the pattern and also calls it a cell-based architecture.
In software, the common failure looks like this. A client calls three services through one shared connection pool. Service A hangs. Requests to A pile up and hold connections. Soon the pool is empty and calls to B and C fail too, even though B and C are healthy.
Two places to apply it
On the consumer side. Give each downstream dependency its own pool of threads, connections or semaphore permits. If A fails, only the pool assigned to A fills up.
On the service side. Partition service instances by consumer or by tenant. If one client sends far too many requests, it overwhelms its own partition while the rest carry on. Queues work the same way: separate queues, or separate worker groups, for separate workloads.
What it has to do with security
The Azure guidance notes that segmentation helps constrain security incidents to the compromised bulkhead. That fits the weakness described in CWE-636, where the suggested design approach is to subdivide resources and components so that a failure in one part does not affect the entire product.
Practical examples:
- A scanner or webhook receiver that processes untrusted input runs in its own pool, so a crafted payload that hangs it does not stall login.
- A premium or critical customer gets a dedicated partition, so a noisy neighbour cannot starve them.
- Background jobs that rebuild indexes cannot take the CPU needed by the authentication path.
Choosing the granularity
More partitions mean better isolation and higher cost. The Azure article lists the trade-offs: resource efficiency drops and complexity grows. Start with the dependencies that have hurt you before, or the ones with the worst failure modes, and leave the rest.
Use platform controls where they exist. Container resource limits, API gateway rate limits and per-workload quotas are better than re-creating throttling in application code. For AI workloads, the same source suggests strict bulkheads around model deployments, since quotas and concurrency limits are tight.
Combine bulkheads with timeouts, circuit breakers and sensible retries. A bulkhead limits damage, but it does not make a slow call fast. See retry storms for the retry side.
How to check you have one
Run a small experiment. Make one dependency return slow responses and confirm that traffic to unrelated dependencies keeps its normal latency. If it degrades, something is still shared: a pool, a thread executor, a database, a rate limit.
Quick check
Is a bulkhead the same as a circuit breaker?
No. A circuit breaker stops calling a failing dependency. A bulkhead caps how many resources any one dependency or consumer can use. They work well together.
Do I need microservices for this?
No. Separate thread pools, queues and processes inside a monolith are bulkheads too.
Sources
Last reviewed: 19 October 2026.