← Concepts

阅读中文版本

Bounded Queue Backpressure

A bounded queue applies backpressure by blocking or rejecting producers when full, so that a slow consumer cannot drive the producer to exhaust memory by buffering an unbounded backlog.

concurrency

Definition

A bounded queue is a fixed-capacity buffer whose producers, when the queue is full, either block (synchronous backpressure) or receive a rejection (reactive backpressure), so that the consumer slowness propagates to the producer instead of accumulating as unbounded memory growth.

Context and scope

Applied in producer-consumer pipelines, actor mailboxes, and any async system where consumer speed is variable and unbounded buffering hides overload.

Common misconceptions

  • An unbounded queue is safe because it never blocks — it never blocks until OOM; the safety is fictional, the failure is just deferred and worse
  • A bounded queue is always slower — it is slower in the no-load case; under load it is faster because it avoids the OOM and GC pause the unbounded queue triggers

Anti-patterns

  • Using an unbounded queue between a fast producer and a slow consumer and relying on OOM as the backpressure signal
  • Choosing a queue capacity so large it never fills, providing backpressure in theory but never in practice

Related concepts

Authoritative source

https://www.reactivemanifesto.org/glossary#Backpressure

What it is

A bounded queue is a fixed-capacity buffer whose producers, when the queue is full, either block (synchronous backpressure) or receive a rejection (reactive backpressure), so that the consumer slowness propagates to the producer instead of accumulating as unbounded memory growth. Applied in producer-consumer pipelines, actor mailboxes, and any async system where consumer speed is variable and unbounded buffering hides overload. The central difficulty is that interleaving is nondeterministic: the set of possible executions grows super-exponentially with the number of operations, and testing samples a vanishing fraction.

How it works

Correctness is established by reasoning about happens-before relationships, not by running more tests. Synchronization primitives are chosen for the specific guarantee needed — mutual exclusion, publication, or ordering — and composed only with a documented proof of absence of deadlock. Bounded resources apply backpressure rather than unbounded queuing that hides overload until memory exhausts.

When to apply and pitfalls

Apply whenever multiple flows share mutable state or resources. The dominant pitfall is reasoning sequentially about concurrent code — “this can’t happen because A finishes before B” — when in fact the scheduler can interleave at any instruction boundary. The second is using a coarse lock for simplicity and turning parallelism back into serialization.