Stream Backpressure
Overview
Backpressure is the most complex mechanical problem in streams. Imagine you are reading from a blazing fast NVMe Hard Drive (Readable Stream), and piping the data across a terrible 3G mobile network (Writable Stream). The Read stream is pumping 500MB/sec, but the Write stream can only send 1MB/sec. The data violently collides and builds up in the server's RAM until it OOM (Out Of Memory) crashes. Backpressure is the internal mathematical mechanism where the Write stream shouts 'STOP! I'M FULL!', forcing the Read stream to pause until the queue clears.
Syntax
// How Backpressure is handled mechanically under the hood:
const readStream = getFastDiskStream();
const writeStream = getSlowNetworkStream();
readStream.on('data', (chunk) => {
// .write() returns a Boolean!
// If it returns FALSE, it means the internal RAM buffer is full!
const canContinue = writeStream.write(chunk);
if (!canContinue) {
console.log("BACKPRESSURE DETECTED! Pausing the read stream...");
// Manually halt the flow of data!
readStream.pause();
}
});
// The Write stream will emit a 'drain' event when it finishes
// flushing its RAM buffer over the network.
writeStream.on('drain', () => {
console.log("Buffer cleared! Resuming the read stream...");
// Turn the flow of data back on!
readStream.resume();
});Common Pitfalls
- Ignoring the boolean return value of
.write(). If you write a custom stream implementation and you just endlessly callwriteStream.write()in awhileloop without checking if it returnedfalse, you completely defeat the backpressure system, inevitably crashing the Node process. - Not understanding the
highWaterMark. This is the internal mathematical threshold (default 16KB for object streams, 64KB for buffers). When the internal queue hits thehighWaterMark,.write()flips fromtruetofalse.
Interview Questions
They use .pipe() or pipeline(). The core C++ logic of those built-in utilities natively calculates the backpressure algorithms for you. It automatically pauses the Read stream when the Write stream gets overwhelmed, and resumes it when the drain occurs.
Real-World Example
Why you never read entire files into RAM before sending them as HTTP responses. If 100 users on slow connections request a 1GB file, your server will hold 100GB in RAM trying to shove it down the network.
// BAD: Server holds the entire file in RAM while waiting for the network
const data = fs.readFileSync('movie.mp4');
res.send(data);
// GOOD: Stream backpressure natively throttles the disk read
// to perfectly match the user's internet speed!
const stream = fs.createReadStream('movie.mp4');
stream.pipe(res);Check Your Knowledge
Test your understanding of Stream Backpressure with these quick questions.