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:
| Stream | What it does | Possible problem |
|---|---|---|
Readable | generates data (for example, reading a file, network, or database) | too fast |
Writable | accepts 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:
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:
const ok = stream.write(chunk);then:
- if the buffer isn't full →
ok = true - if the buffer is full →
ok = 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:
Readable (produces 100 KB/sec)
↓
Writable (can only write 30 KB/sec)
↓
Writable's buffer fills up → backpressureAt this moment:
.write()returnsfalse;- Node.js pauses reading (
readable.pause()); - Once Writable flushes its buffer to disk → the
drainevent fires; - Node.js resumes reading (
readable.resume()).
An example where backpressure clearly shows up
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:
readable.pipe(transform).pipe(writable);Node.js does the same thing automatically:
- if
writablereturnsfalse→ reading stops; - as soon as
drainfires → reading resumes.
In other words, backpressure is built into the pipe() system and needs no manual handling.
Factors that make backpressure worse
| Cause | Example |
|---|---|
| Slow disk writes | HDDs, network storage |
| Compression or encryption in Transform streams | zlib, crypto |
| A slow server response during an HTTP write | res.write() slower than reading |
Large chunk sizes or a small highWaterMark | the buffer fills too fast |
Complex synchronous logic in _write() | blocks the event loop |
Visualizing the process
┌────────────────────────────────┐
│ 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()orpipeline(), they manage backpressure automatically - Tune
highWaterMarkfor your workload - Keep Transform streams efficient and non-blocking
- Avoid synchronous operations inside streams
Short Answer
Interview readyA concise answer to help you respond confidently on this topic during an interview.