Skip to content

Streams & I/O

The problem with loading everything at once

Section titled “The problem with loading everything at once”

Imagine reading a 4 GB log file. If you load it all into memory first, Node has to allocate 4 GB before you can inspect a single line. On a machine with 2 GB of RAM, the process crashes before it begins.

Streams solve this by processing data in chunks — you start reading the first chunk while the rest is still arriving from disk or network. Memory stays bounded regardless of how large the source is.

The same insight applies to writing: instead of buffering an entire response in memory and sending it all at once, a stream pipes each chunk to the destination as it arrives.

Node.js defines four abstract stream types in the node:stream module:

TypeDirectionExample
ReadableData flows outfs.createReadStream, process.stdin
WritableData flows infs.createWriteStream, process.stdout
DuplexBidirectionalTCP socket (net.Socket)
TransformBidirectional with transformationzlib.createGzip (compresses in-flight)

Every stream is also an EventEmitter. The stream base classes emit standard events (data, end, error, drain, finish) that you attach handlers to.

LessonTopic
Readable Streamsdata/end/error events, Readable.from, async iteration
Writable Streamswrite(), end(), and the drain event
Pipe & PipelineConnecting streams with .pipe() and stream.pipeline()
BackpressureWhat it is, why it matters, and how pipelines handle it

The demo below uses Readable.from to create a readable stream from an array of strings, then consumes it chunk by chunk with for await. Notice that no full array is ever held in a buffer — each item is yielded on demand.

Node.js

Needs the Node.js runtime — open in StackBlitz to run.

Why are streams preferred over loading an entire file into memory?
Which Node.js stream type transforms data as it passes through?
What base class do all four Node.js stream types extend?