Skip to main content
Pattern

Backpressure

Problem

Producers publish faster than consumers can process. Queues grow unbounded, memory fills up, and everything crashes.

Context

Any producer-consumer relationship where the two sides can drift in throughput.

Solution

Consumers signal upstream when they're overwhelmed (queue depth threshold, memory pressure). Producers slow down (block writes, return 429, buffer to disk, or drop low-priority messages). Reactive Streams codifies this with 'demand-based' consumption — consumers pull only what they can handle.

Trade-offs

  • Producers must handle the 'slow down' signal — either block, drop, or apply their own backpressure upstream
  • Slower producers = slower end-to-end throughput (that's the point)
  • Backpressure signals can be racy — by the time producer sees the signal, queue has grown more

Failure modes

  • Producer ignores backpressure and buffers locally → memory blowup
  • Backpressure signal is delayed → queue grows before signal reaches producer
  • Cascading backpressure blocks the whole pipeline

When to use

  • Streaming pipelines (Flink, Kafka Streams)
  • Async processing where consumers can be slow
  • Any bounded resource downstream that can be overwhelmed

When NOT to use

  • Synchronous request/response — the client waiting is natural backpressure
  • Fire-and-forget with drop-OK semantics