Skip to main content
cd ../lexicon
sys/docs/lexicon/head-of-line-blocking-hol-blocking.md
Lexicon

Head-of-Line Blocking (HOL Blocking)

Difficulty: Advanced
2 min read

In plain English

Plain definition

When several unrelated pieces of work share one strictly ordered pipe, one slow or lost piece at the front forces everything behind it to wait, even if those later pieces have nothing to do with the delay.

HOL blocking occurs at any layer that imposes strict FIFO ordering on a shared channel while multiplexing logically independent streams over it. The canonical case is TCP: when multiple application-level streams (e.g. multiple HTTP/2 requests) are multiplexed over a single TCP connection, a single lost segment forces the kernel’s receive buffer to withhold all subsequent segments, including those belonging to unrelated streams that arrived intact, until retransmission and in-order delivery completes. This is why HTTP/2, despite offering stream multiplexing at the application layer, remains vulnerable to HOL blocking at the transport layer — a key motivation for QUIC/HTTP3, which multiplexes independent streams with independent loss recovery, so one stream’s retransmit does not stall the others.

The pattern recurs far above the transport layer. Connection pooling against a backend with synchronous, ordered response semantics (e.g. Redis pipelining, or older MySQL protocol implementations) exhibits the same failure mode: a slow query at the head of the pipeline blocks all queued responses behind it, even on an otherwise idle connection. Similarly, single-threaded event loop workers (or any actor with an unbounded mailbox) suffer HOL blocking when one message triggers a long-running or blocking syscall — every subsequent message, regardless of priority or independence, waits.

  • Load balancer / connection reuse: keep-alive connections to an upstream that itself serializes handling internally reintroduce HOL blocking even if the client-side multiplexing layer is HOL-free.
  • Message queues: a single-partition Kafka consumer processing messages sequentially will stall all downstream consumption behind one poison-pill or slow-to-process message; this is why partitioning by independent keys is the primary mitigation, not consumer parallelism alone.
  • gRPC streaming: server-streaming RPCs multiplexed over HTTP/2 inherit the transport-level vulnerability described above under packet loss, particularly visible on lossy or high-RTT links.

Mitigations generally fall into three categories: eliminate shared ordering constraints (per-stream loss recovery as in QUIC, per-partition parallelism in queues), bound the blast radius (per-connection timeouts, circuit breakers, dedicated connection pools per logical tenant/priority class), or make ordering explicit and cheap to skip (out-of-order acknowledgment protocols, request pipelining with response correlation IDs rather than strict FIFO). Diagnostically, HOL blocking is notoriously difficult to spot from aggregate throughput metrics alone — it presents as elevated p99/p999 latency with normal p50 and normal error rates, and is often misattributed to GC pauses or backend slowness before the shared-queue serialization is identified as the root cause.