How to Handle Backpressure in Node.js Streams
Backpressure is what happens when data arrives faster than it can be processed — and handling it is what stops your Node.js app from ballooning in memory and crashing. Ignore it and a fast reader will flood a slow writer's buffer until you run out of memory.
The problem, concretely
Imagine reading from a fast disk and writing to a slow network. If you keep writing without checking whether the destination has kept up, data piles into an in-memory buffer that grows without limit. That is unmanaged backpressure.
The signal: write() returns false
A writable stream's write() returns false when its internal buffer is full. That is your cue to stop writing and wait for the stream to catch up, which it signals with the 'drain' event:
if (!writable.write(chunk)) { readable.pause(); writable.once('drain', () => readable.resume()); }
The easy way: let pipe handle it
The good news is that pipe() and stream.pipeline() handle backpressure for you automatically — pausing the source when the destination is full and resuming on drain. This is a major reason to prefer piping over manual read/write loops. See streams explained.
When you must handle it manually
If you write your own loop or a custom stream, respect the write() return value and the 'drain' event as above. For readable streams, honour pause() and resume(), or use the async iterator interface which applies backpressure naturally.
Frequently asked questions
Do I need to worry about backpressure if I use pipe()?
Generally no — pipe() and pipeline() manage it for you. You mainly need manual handling when writing custom streams or bespoke read/write loops.
What are the symptoms of ignored backpressure?
Steadily rising memory usage during large transfers, and eventually an out-of-memory crash. If memory grows with data volume, unmanaged backpressure is a prime suspect.
Does async iteration handle backpressure?
Yes — iterating a readable stream with for await...of applies backpressure naturally, since each iteration waits for you to finish before pulling the next chunk. It is a clean, modern approach.
Was this article helpful?