- Backpressure: Readable produce data nhanh hơn Writable consume — nếu không xử lý, data buffer trong memory vô hạn cho đến khi OOM crash. highWaterMark: ngưỡng buffer size (default 16KB cho object streams, 16384 bytes cho byte streams) — khi buffer vượt ngưỡng, stream signals slow down.
- Cơ chế manual:
writable.write(chunk)trả vềfalsekhi internal buffer đầy → stop reading; lắng nghewritable.on('drain', resume)để tiếp tục.
Ví dụ file upload: client upload 1GB/s, DB write chỉ 100MB/s — không có backpressure thì 900MB/s tích lũy trong RAM. pipe() tự xử lý nhưng không handle errors tốt. pipeline() API (stream/promises): await pipeline(req, transform, fs.createWriteStream(dest)) — tự xử lý backpressure VÀ cleanup tất cả streams khi error/complete, không leak.
- Backpressure: a Readable produces data faster than a Writable can consume it — without handling this, data buffers in memory indefinitely until an OOM crash. highWaterMark: the buffer size threshold (default 16KB for object streams, 16384 bytes for byte streams) — when the buffer exceeds this, the stream signals to slow down.
- Manual mechanism:
writable.write(chunk)returnsfalsewhen the internal buffer is full → stop reading; listen forwritable.on('drain', resume)to continue. - File upload example: client uploads at 1GB/s, DB writes only at 100MB/s — without backpressure, 900MB/s accumulates in RAM.
pipe()handles this automatically but doesn't handle errors well.pipeline()API (stream/promises):await pipeline(req, transform, fs.createWriteStream(dest))— handles backpressure AND cleans up all streams on error/completion, no leaks. - Transform streams: implement
_transform(chunk, enc, callback), callcallback()when ready for the next chunk — naturally creates backpressure.
Pitfall: .on('data', handler) puts the stream in flowing mode, bypassing backpressure — use async iteration for await (const chunk of readable) instead.