Backpressure in Streams API

Slap yourself if

You think backpressure is just buffering more or slowing the producer with setTimeout.

Why this exists

Backpressure exists because producers and consumers operate at different speeds, and pretending they don’t leads to memory blowups, jank, or dropped data. Streams formalize this imbalance instead of hiding it.

Mental model

A stream is a contract between producer and consumer about pace. Backpressure is the feedback channel that says when more data is safe — not a performance optimization, but a correctness mechanism.

  • A producer enqueues chunks into a stream.
  • The consumer pulls data at its own pace.
  • The stream tracks internal queue size and desiredSize.
  • When capacity is exceeded, the producer is signaled to slow down or stop.
  • Ignoring desiredSize and over-enqueuing.
  • Assuming streams auto-throttle without cooperation.
  • Treating backpressure as optional in custom sources.
  • Bridging streams to callbacks and losing flow control.

Backpressure in the Streams API is the mechanism that propagates consumer capacity back to the producer, preventing unbounded buffering by coordinating how fast data is produced and consumed.

  • ReadableStreams without pull awareness
  • Manual buffering layered on top of streams
  • Unbounded queues or arrays
  • Assuming GC will handle excess data

Deep dive

Requires Pro

Premium deep dives include more internals, more scars.

How backpressure is enforced internally

How ignoring backpressure breaks apps

Throughput versus stability

Debugging backpressure issues

When Streams backpressure is unnecessary