streams — Streams
Processing data incrementally in Node.js — Readable, Writable, Transform streams, pipeline, and async iteration.
What it is, in plain English: Streams are Node.js's way of processing data piece by piece, without loading the whole thing into memory. A Readable stream produces data. A Writable stream consumes data. A Transform stream does both — it receives data, transforms it, and outputs the result. pipeline() connects streams together and handles errors and cleanup. Streams implement the async iterable protocol — you can use for await...of.
Why streams — memory-efficient data processing
Without streams, to process a large file you load it all into memory. A 10GB log file would need 10GB of RAM. Streams process data in small chunks — the same task uses only kilobytes of memory.
The four stream types
// Readable — source of data
// Writable — destination for data
// Transform — reads, transforms, writes (both ends)
// Duplex — separate read and write (like a TCP socket)
// You use streams constantly without realising it:
process.stdin; // Readable
process.stdout; // Writable
fs.createReadStream("file.txt"); // Readable
fs.createWriteStream("out.txt"); // Writable
zlib.createGzip(); // Transform
http.IncomingMessage; // Readable (req in createServer)
http.ServerResponse; // Writable (res in createServer)Reading a stream with async iteration
import { createReadStream } from "fs";
import { createInterface } from "readline";
// Read a large file line by line (memory-efficient):
const rl = createInterface({
input: createReadStream("large.csv"),
crlfDelay: Infinity,
});
let lineNumber = 0;
for await (const line of rl) {
lineNumber++;
if (lineNumber === 1) continue; // skip header
processRow(line.split(","));
}
console.log(`Processed ${lineNumber} lines`);pipeline — the correct way to connect streams
import { createReadStream, createWriteStream } from "fs";
import { createGzip } from "zlib";
import { pipeline } from "stream/promises";
// Compress a file:
await pipeline(
createReadStream("big-file.json"), // read
createGzip(), // compress
createWriteStream("big-file.json.gz") // write
);
// pipeline: handles backpressure, errors, and cleanup automatically
// ✗ Don't use .pipe() directly — it doesn't handle errors:
// readStream.pipe(gzip).pipe(writeStream); // if gzip fails, streams don't close!
Try It Yourself
Official Sources
- Node.js Docs — stream
- Node.js Docs — stream.pipeline()
- Node.js Docs — Streams — Backpressuring in Streams
The Codex links only to official documentation and the ECMAScript specification. No third-party tutorials.