Everything a Node process takes from the outside world arrives as bytes. A Buffer is a fixed block of memory you can index, slice and decode. A stream delivers an unbounded sequence of buffers over time, with flow control that stops a fast producer from overwhelming a slow consumer.
The choice is not stylistic: the code below sums a column of a 108 MB CSV twice.
// sum-whole.js — read it all, then split
const text = await readFile('orders.csv', 'utf8');
for (const l of text.split('\n')) total += Number(l.slice(l.lastIndexOf(',') + 1)) || 0;
// sum-stream.js — one line at a time
const lines = createInterface({ input: createReadStream('orders.csv') });
for await (const l of lines) total += Number(l.slice(l.lastIndexOf(',') + 1)) || 0;Output
sum-whole.js total 2990974593.0 rss 559 MB heap 438 MB 1606 ms sum-stream.js total 2990974593.0 rss 74 MB heap 17 MB 1908 ms
The streaming version costs 20% more time and one seventh of the memory, and its memory does not grow with the file: the same code handles a 10 GB export on a 512 MB container. That ratio decides how many requests a server handles at once.