Stream Types (Readable, Writable, Duplex, Transform)
Node.js has four stream types: Readable (source of data), Writable (sink for data), Duplex (both readable and writable, e.g., TCP socket), and Transform (duplex that transforms data as it passes through, e.g., zlib).
Four types of water pipes: Readable = faucet (source), Writable = drain (sink), Duplex = garden hose (water flows both ways), Transform = water filter (changes what passes through). Every pipe has a pressure gauge (highWaterMark).
Readable streams emit 'data' events in flowing mode or yield data via .read() in paused mode. Writable streams accept data via .write() and signal completion with .end(). Transform streams implement _transform(chunk, encoding, callback) to modify data in transit. Custom streams are created by subclassing the base classes and implementing _read/_write/_transform. Node.js 16+ stream.Readable.from() creates a readable from an async iterable, enabling async generator-based stream composition.
Internally, readable streams maintain a highWaterMark buffer. When the buffer fills, the stream stops calling _read (pauses the source). Writable streams also have a highWaterMark; write() returns false when the internal buffer exceeds it, signaling the producer to stop. Transform streams must call callback() in _transform to signal readiness for more input—forgetting it causes the stream to stall silently. ObjectMode streams (objectMode: true) pass JavaScript objects rather than Buffers/strings, with highWaterMark counting objects instead of bytes.
Node has four stream types: Readable, Writable, Duplex (both), Transform (duplex that modifies data). The core contract: Readable produces data; Writable consumes it. Transform sits in between. The critical operational concern is backpressure—each stream type has a highWaterMark buffer, and producers must respect write() return values to avoid memory overflow.
ObjectMode streams change highWaterMark semantics: instead of bytes, it counts object instances. A highWaterMark of 16 in object mode buffers 16 objects, not 16 bytes. A stream of large objects in objectMode can silently buffer gigabytes before backpressure kicks in.