Node.js stream.pipeline - Process Large Files Without Memory Overflow
Problem
Tried to read a multi-GB log file with fs.readFile and ran out of memory. Obvious in hindsight, but easy to forget.
// This loads the entire file into memory
const data = await fs.promises.readFile('huge.log', 'utf-8');
Solution
Use stream.pipeline to create a read-transform-write pipeline that processes data in chunks. Error handling and stream cleanup are automatic.
const { pipeline } = require('stream/promises');
const fs = require('fs');
const zlib = require('zlib');
// Compress a large file while copying
await pipeline(
fs.createReadStream('huge.log'),
zlib.createGzip(),
fs.createWriteStream('huge.log.gz')
);
For line-by-line processing, insert a Transform stream.
const { Transform } = require('stream');
const lineFilter = new Transform({
transform(chunk, encoding, callback) {
const lines = chunk.toString().split('\n');
const errors = lines
.filter(line => line.includes('ERROR'))
.join('\n');
callback(null, errors ? errors + '\n' : '');
}
});
await pipeline(
fs.createReadStream('huge.log'),
lineFilter,
fs.createWriteStream('errors-only.log')
);
Key Points
pipelinefromstream/promisesworks naturally with async/await- On error, it automatically destroys all streams in the pipeline — the key advantage over
.pipe()chaining - Memory usage stays constant regardless of file size. Works the same for 10GB or 100GB files