CMD Guide
HomeSystem DesignMicroservices Patterns

Introduction

Bulkhead: compartmentalize so one leak does not sink the ship

On a ship, bulkheads limit flooding to one compartment. In software, a bulkhead limits how much of a service's finite concurrency (threads, connections, memory, CPU) any one dependency or workload class may consume. If that compartment saturates, only that class fails fast — critical paths keep their reserved capacity.

Michael Nygard's stability patterns treat bulkheads as first-class isolation, complementary to timeouts and circuit breakers. Breakers stop calling a sick dependency; bulkheads ensure that even while you are still calling (or waiting), you cannot steal the whole process.

The cascade bulkheads prevent (Little's Law)

Checkout service: shared pool of 200 threads. Calls Payment (20 ms) and Recommendations (20 ms). At 500 RPS, healthy in-flight per dependency ≈ 500 × 0.02 = 10 — comfortable.

Recommendations slows to 5 s. Needed concurrency for recommendations alone: 500 × 5 = 2,500. You only have 200 threads. Within a fraction of a second every thread waits on recommendations. Payment is healthy but checkout cannot call it — critical path dies because of an optional feature.

Bulkhead fix: give recommendations a dedicated pool or semaphore of e.g. 40 permits. When it saturates, recommendation calls fail fast or skip; the remaining 160 threads still serve payment and core checkout.

Mechanism: what you actually implement

The cap must be hard. Elastic pools that grow without limit recreate the shared-pool failure.

Decision table

SituationBulkhead?Notes
Multiple outbound deps, unequal criticalityYesClassic win (payment vs ads vs recommendations)
Single dependency onlyUsually noNothing to isolate from; focus timeout/breaker
Multi-tenant noisy neighborYesPer-tenant concurrency quotas
Latency-critical path + batch jobs in same processYesSeparate pools so batch cannot stall interactive
Capacity already huge vs loadMaybe laterStill wise as guardrail; cost is idle reserved capacity

When NOT to bulkhead

Cost: reserved capacity idle when healthy; more tuning; risk of over-partitioning (each slice too small → constant reject under normal load).

Escalation: shuffle sharding when tenants ≫ pools

A per-tenant semaphore isolates each tenant but needs one pool per tenant — untenable at thousands of tenants. Shuffle sharding gets most of the isolation with a fixed number of cells. Split the workers into n cells and pin each tenant to a random subset of k cells (its "shard"); route that tenant's work only to those k.

The isolation comes from combinatorics. With n = 8 cells and k = 2 per tenant there are C(8,2) = 28 possible shards, so two tenants land on the exact same pair only 1/28 ≈ 3.6% of the time. One abusive tenant can saturate at most its own 2 of 8 cells (25%); every other tenant keeps at least one clean cell unless it happened to draw that same rare pair — and a client that retries across its k cells rides out the collision. Blast radius drops from "one global pool, everyone down" to "at most a 1/28 pairing, and even then only partially."

Prefer shuffle sharding over per-tenant semaphores when the tenant count far exceeds the pools you can afford to run, and you can tolerate a small collision probability instead of guaranteeing per-tenant isolation. Keep in-process semaphores when tenants are few and you want a hard, exact quota each.

Sizing sketch

For dependency D: permits ≈ ceil(RPS_D × p99_latency_D × safety), then cap by how much of total capacity you are willing to lose if D is sick. Example: optional reco at 500 RPS, p99 50 ms healthy → ~25 permits; set 40 to absorb spikes; never 200.

Pitfalls and detection

Alerts: bulkhead reject rate, pool active/max, dependency latency, saturation duration.

Drill ladder

  1. Q: 200 threads, 500 RPS, dep latency 5 s. Steady-state threads needed? A: L = λW = 500 × 5 = 2,500 — impossible; saturation guaranteed without isolation/load-shed.
  2. Q: Semaphore vs thread pool bulkhead — one trade-off. A: Semaphore: lighter, caller thread blocks in call; pool: isolates thread use, higher overhead, can time out queue independently.
  3. Q: Why does circuit breaker not replace bulkhead? A: Breaker opens after failures accumulate; bulkhead protects capacity during the slow phase before/without open, and partitions healthy vs optional deps.

Sources: Nygard, Release It!; Resilience4j/Hystrix isolation models; Little's Law for sizing.

🤖 Don't fully get this? Learn it with Claude

Stuck on Introduction? Open Claude, copy a block below, and it'll teach you this exact concept — visually and interactively.

🎨 Explain it visually

Build the mental picture, not memorization.

I just read a lesson on **Introduction** (System Design) and want to truly understand it. Explain Introduction from first principles using ONE vivid real-world analogy and a visual mental model — draw it as ASCII art or a clear step-by-step diagram — with a concrete example using real numbers. Then ask me one question to check I got the mental picture, and wait for my reply. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.
🤔 Walk me through it (interactive)

Socratic — adapts to where you're stuck.

Teach me **Introduction** interactively. Ask me ONE guiding question at a time, wait for my answer, and adapt to my confusion — build the idea with me step by step instead of explaining it all at once. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.
🧪 Quiz me & fix my gaps

Active recall exposes what you missed.

Quiz me on **Introduction** with 5 questions, easy to tricky, ONE at a time. Tell me if each answer is right; at the end, explain clearly what I got wrong and why. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.
🧠 Make it stick

Intuition + hook + flashcards for long-term memory.

Help me remember **Introduction** for the long term: give the one-sentence intuition, a memorable hook/mnemonic, a tiny worked example, and 3 active-recall flashcards (Q -> A). If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.

📝 My notes