Skip to content
tezvyn:
Menu

Backpressure in Node.js streams

Source: interviewHardHow cards are made

Summary

flow control between fast producer and slow consumer.

Key points

backpressure pauses the readable when the writable buffer fills, pipe and pipeline manage it automatically, pipeline also propagates errors and cleans up.

What's really being asked

This evaluates deep stream knowledge and whether you can prevent unbounded memory growth when one side of a data flow is slower than the other, a real concern when serving large files to slow clients.

The full answer

Backpressure is the feedback signal that prevents a fast readable stream from overwhelming a slower writable one. Each writable has an internal buffer bounded by its highWaterMark. When you write data faster than it can be flushed, the write call returns false, indicating the buffer is full. The producer should then stop until the writable emits a drain event signaling room is available. Without this, data piles up in memory until the process runs out. The pipe method handles all of this automatically: it pauses the source when the destination returns false and resumes on drain, keeping memory bounded. stream.pipeline does everything pipe does and additionally propagates errors through a single callback or promise and guarantees all streams are properly destroyed if any link fails, avoiding leaked file descriptors. This is why pipeline is preferred in modern code.

The mistakes people make

Thinking backpressure is about network bandwidth alone rather than buffer-level flow control. Writing in a loop while ignoring write's false return, which defeats backpressure. Believing pipe handles error cleanup, which it does not, leading to leaks.

What usually comes next

What is highWaterMark and how does tuning it affect throughput. Why does pipe leave streams open on error. How does async iteration over a stream interact with backpressure.

A concrete example

Serving a 2GB file to a client on a slow connection: fs.createReadStream(file).pipe(res) pauses disk reads whenever the socket's send buffer fills and resumes on drain, so memory stays near the highWaterMark. A naive readFile-then-write approach would buffer the whole 2GB. Using pipeline(readStream, res, err => {}) adds clean error handling if the client disconnects mid-transfer.

Interview question

What advantage does stream.pipeline have over the .pipe() method when streaming a file to an HTTP response?

  • a.pipeline propagates errors and destroys all streams on failure, preventing leaksCorrect
  • b.pipeline transfers data faster by skipping the internal buffer
  • c.pipeline encrypts the stream contents automatically
  • d.pipeline disables backpressure for maximum throughput
Why?

pipeline adds unified error handling and resource cleanup that pipe lacks, avoiding leaked descriptors. Both honor backpressure; pipeline does not skip buffering, drop backpressure, or encrypt data.

Just read this? Test yourself on what you have been reading.

Read the original → nodejs.org

Put your scrolling time to good use

Learn one idea, try a quiz and save useful cards for revision. Tezvyn makes it easy to learn and stay current in your tech field, a few minutes at a time.

The iPhone app is on the way

We are building it. Until it lands, nothing here is held back from you: every interview card, your saved cards, streaks and the job board all work in Safari, plus hundreds of free practice quizzes of thirty questions each. Sign in and it all carries over to the app the day it arrives.

Want it as an icon? Tap Share at the bottom of Safari, then Add to Home Screen. It opens full screen and the cards you have read stay available offline.

Get it on Google PlayiPhone app coming soon

We are hiring for this. Open roles that interview on nodejs — each one lists the topics its interview covers.

See open roles