advanced

Streams

Process data incrementally with readable, writable, duplex, transform streams, pipelines, errors, and backpressure.

Streams process data in chunks instead of loading entire payloads into memory. Node provides four base types:

| Type | Role | |------|------| | Readable | Source — `read()`, `'data'`, `'end'` | | Writable | Sink — `write()`, `end()`, drain events | | Duplex | Independent read/write (e.g. TCP socket) | | Transform | Duplex that modifies data (gzip, JSON lines) |

Prefer `stream/promises.pipeline` for automatic error propagation and cleanup:

					import { createReadStream } from 'node:fs';
import { createGzip } from 'node:zlib';
import { pipeline } from 'node:stream/promises';

await pipeline(
  createReadStream('access.log'),
  createGzip(),
  createWriteStream('access.log.gz'),
);
				

Object mode streams carry JavaScript objects instead of Buffers/strings — useful for ETL, dangerous if producers outpace consumers.

On interviews: explain why streaming beats `readFile` for large files, how backpressure signals slow producers, and how pipeline differs from manual `.pipe()`.

Common pitfalls: listening to `'data'` without pausing and overwhelming memory; forgetting error handlers on piped streams; mixing callback and promise APIs without awaiting pipeline.

The trade-off is balancing simplicity, performance, safety, and operability — name which axis you optimized and what cost you accepted.

Checklist:

  • Name four stream types and a use case each.
  • Use `pipeline` for error-safe composition.
  • Handle `'error'` on every leg.
  • Respect `write()` return value and `'drain'`.