What are streams and why do they matter?
Take a moment.
Say your answer out loud or write it down first — retrieval is what makes it stick. Reveal when you're ready.
Short answer
Streams process data incrementally in chunks instead of buffering everything in memory — readable, writable, duplex and transform types. They matter for handling large files/network data with constant memory and backpressure control.
Detailed explanation
Reading a 10GB log into a Buffer exhausts memory; streams deliver manageable chunks as they arrive, keeping usage flat regardless of input size. Four types cover the patterns: Readable (file reads, HTTP requests), Writable (writes, responses), Duplex (both directions — sockets), Transform (modify en route — zlib compression, encryption). Pipes compose them: readable.pipe(zlib.createGzip()).pipe(writable) or the modern pipeline()/pipeline promise API which propagates errors and cleans up properly — pipe() famously swallows errors. Backpressure is the key mechanism: if the destination writes slowly, stream pauses the source automatically so fast producers don't drown slow consumers. Everyday encounters: Express serving files, proxying requests, CSV parsing line-by-line, video streaming ranges. HighWaterMark tunes chunk buffering when profiling shows pressure.
Example
import { createReadStream, createWriteStream } from 'node:fs';
import { createGzip } from 'node:zlib';
import { pipeline } from 'node:stream/promises';
// Compress a huge file with ~constant memory:
await pipeline(
createReadStream('access.log'), // readable
createGzip(), // transform
createWriteStream('access.log.gz'), // writable
); // errors propagate & cleanup handled automaticallyInterview tip
Lead with the memory story (10GB file example), then name backpressure explicitly — it's the concept interviewers listen for — and recommend pipeline over pipe for error safety.
Common mistakes
- Using pipe() without error handling.
- Not knowing what backpressure means.