Explain the difference between `pipe()` and `on('data')` when working with streams.
Difficulty: 5/10
streams, pipe, event handling
pipe(): Used to connect streams and automatically handle data flow from one stream to another.
on('data'): An event listener that allows you to manually handle incoming data as it's emitted by a readable stream.
Scenario Questions
0-2 years experience
1You need to copy the contents of one file to another using streams. Would you use pipe() or attach a 'data' listener, and why?
2If you add a 'data' listener to a readable stream but never call stream.resume(), what will the program do?
3What changes, if any, occur when you call pipe() on a stream that already has a 'data' listener attached?
2-5 years experience
1While building a JSON‑line parser, you switched from pipe() to manual 'data' handling to log progress, but the parser now emits chunks out of order under load. What could be causing this and how would you fix it?
2During a file upload you replaced pipe() with a 'data' listener to add custom headers, and the upload stalls when many users upload simultaneously. Explain why this might happen.
3An error from the source stream is not reaching your error handler when you use pipe(), but it does when you listen to 'data' events. Why does this occur?
5-8 years experience
1Design a streaming pipeline that validates, transforms, and writes large CSV files to a database. Discuss where you’d use pipe() versus manual 'data' handling, focusing on backpressure and error propagation.
2Your service streams data from a remote API to clients over HTTP/2. How do you ensure backpressure is respected across the network boundary, and what role does pipe() play compared to 'data' events?
3You need to collect per‑chunk metrics and sometimes branch the stream based on content. How would you implement this without breaking backpressure, and why might you avoid pipe() for those stages?
8+ years experience
1The team is migrating a legacy codebase that heavily uses 'data' listeners to a newer architecture that prefers pipe() for composability. What architectural considerations and migration steps would you propose?
2In a distributed data‑processing platform you must support both Node.js streams and external pull‑based consumers. How would you design an abstraction that can switch between pipe() and manual data handling while preserving backpressure and observability?
3When evaluating a new streaming library, you need to decide whether to expose a pipe() API or an event‑emitter API to downstream teams. What long‑term maintenance, performance, and developer‑experience factors influence that decision?
Follow-up Questions
How does backpressure differ between pipe() and manual data listeners?
What happens if an error is emitted on the source stream when using pipe()?
Can you describe a scenario where you’d prefer a 'data' listener over pipe()?
Sharethis question
Share via WhatsApp, X, Facebook, LinkedIn or copy link. Open Graph preview enabled.