Skip to main content

How does backpressure arise?

A quick reminder of the definition

Backpressure is a situation where the consumer (Writable) can't process data as fast as the producer (Readable) generates it.

The key cause

A mismatch between stream speeds:

StreamWhat it doesPossible problem
Readablegenerates data (for example, reading a file, network, or database)too fast
Writableaccepts and writes data (for example, to a file, HTTP, or database)too slow

When Writable can't keep up, its internal buffer fills up. At that point, Node.js stops reading from the source, so it doesn't flood the system with data.

What this looks like "inside"

Every Writable Stream has an internal buffer (highWaterMark).

Example:

javascript
const stream = fs.createWriteStream('out.txt', { highWaterMark: 16 * 1024 });

Here highWaterMark = 16 KB is the limit on how much data the stream can hold in its buffer.

When you call:

javascript
const ok = stream.write(chunk);

then:

  • if the buffer isn't full → ok = true
  • if the buffer is fullok = false

And that's exactly the moment backpressure appears. It's a signal: "stop, don't write any more until I free up."

When exactly this happens

Schematically:

javascript
Readable (produces 100 KB/sec) Writable (can only write 30 KB/sec) Writable's buffer fills up → backpressure

At this moment:

  1. .write() returns false;
  2. Node.js pauses reading (readable.pause());
  3. Once Writable flushes its buffer to disk → the drain event fires;
  4. Node.js resumes reading (readable.resume()).

An example where backpressure clearly shows up

javascript
const fs = require('fs'); const readable = fs.createReadStream('big.txt'); const writable = fs.createWriteStream('copy.txt', { highWaterMark: 1024 }); // a 1 KB buffer readable.on('data', (chunk) => { const ok = writable.write(chunk); console.log('Writing...', ok ? 'OK' : 'Buffer full!'); if (!ok) { readable.pause(); // pause reading writable.once('drain', () => readable.resume()); } }); readable.on('end', () => writable.end());

Here writable.write() returns false when the stream can't keep up, that's exactly the moment backpressure appears.

In stream chains (pipe() and pipeline())

If you use:

javascript
readable.pipe(transform).pipe(writable);

Node.js does the same thing automatically:

  • if writable returns false → reading stops;
  • as soon as drain fires → reading resumes.

In other words, backpressure is built into the pipe() system and needs no manual handling.

Factors that make backpressure worse

CauseExample
Slow disk writesHDDs, network storage
Compression or encryption in Transform streamszlib, crypto
A slow server response during an HTTP writeres.write() slower than reading
Large chunk sizes or a small highWaterMarkthe buffer fills too fast
Complex synchronous logic in _write()blocks the event loop

Visualizing the process

javascript
┌────────────────────────────────┐ Readable Stream └──────────────┬─────────────────┘ Writable's buffer (16 KB) ┌──────────────────────────────┐ │ ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ │ ← full └──────────────────────────────┘ write()false (Backpressure!) ↓ wait for drain()resume()

In short

Backpressure arises when the Writable Stream can't keep up processing incoming data, and it tells the Readable Stream to pause, until the buffer frees up.

How to deal with it

  • Use pipe() or pipeline(), they manage backpressure automatically
  • Tune highWaterMark for your workload
  • Keep Transform streams efficient and non-blocking
  • Avoid synchronous operations inside streams

Short Answer

Interview ready
Premium

A concise answer to help you respond confidently on this topic during an interview.