DEV Community

Cover image for 🚀 Day 12 of My Node.js Learning Journey: Mastering Streams & Backpressure 📂⚡
Krati Joshi
Krati Joshi

Posted on

🚀 Day 12 of My Node.js Learning Journey: Mastering Streams & Backpressure 📂⚡

One of the biggest strengths of Node.js is its ability to process large amounts of data efficiently. Today, I explored Streams, one of the most important concepts for backend development and a frequently asked topic in Node.js interviews.

💡 What are Streams?

A Stream is a way to process data chunk by chunk instead of loading the entire file into memory.

Instead of reading a 2 GB file at once, Node.js reads small chunks (typically 64 KB for fs.createReadStream()), making applications much more memory-efficient and scalable.

Why use Streams?

✅ Lower memory usage

✅ Faster processing

✅ Better performance

✅ Ideal for large files

✅ Non-blocking data transfer


📦 What is a Chunk?

A chunk is a small piece of data transferred by a stream.

Instead of:

2 GB File
      ↓
Load everything into RAM
Enter fullscreen mode Exit fullscreen mode

Streams work like this:

2 GB File
      ↓
64 KB
      ↓
64 KB
      ↓
64 KB
      ↓
...
Enter fullscreen mode Exit fullscreen mode

This is why Node.js can efficiently handle file uploads, downloads, video streaming, and large datasets.


🌊 Types of Streams

Node.js provides four types of streams:

📖 Readable Stream

Used to read data from a source.

Examples:

  • fs.createReadStream()
  • HTTP Request
  • process.stdin

✍️ Writable Stream

Used to write data to a destination.

Examples:

  • fs.createWriteStream()
  • HTTP Response
  • process.stdout

🔄 Duplex Stream

Can both read and write data.

Examples:

  • TCP Sockets
  • Network connections

⚙️ Transform Stream

A special type of Duplex Stream that modifies data while passing it through.

Examples:

  • Compression (zlib.createGzip())
  • Encryption
  • Decryption

🚀 pipe() — The Easiest Way to Transfer Data

Instead of manually reading and writing chunks:

const fs = require("fs");

const readStream = fs.createReadStream("input.txt");
const writeStream = fs.createWriteStream("output.txt");

readStream.pipe(writeStream);
Enter fullscreen mode Exit fullscreen mode

Benefits of pipe()

  • Less code
  • Automatic chunk transfer
  • Handles flow efficiently
  • Automatically ends the destination stream
  • Manages backpressure internally

🌊 Understanding Backpressure

One of the most interesting concepts I learned today was Backpressure.

Imagine:

  • 📥 Producer can generate 100 MB/sec
  • 📤 Consumer can process only 20 MB/sec

Without flow control, data would keep accumulating in memory.

Backpressure solves this by pausing the producer until the consumer catches up, preventing unnecessary memory growth and improving stability.

Node.js handles this automatically when using pipe().


💧 highWaterMark

highWaterMark defines the buffer threshold that helps determine when backpressure should start.

Some useful defaults:

  • fs.createReadStream()64 KB
  • Most Readable Streams → 16 KB
  • Most Writable Streams → 16 KB

It's important to remember that highWaterMark is a threshold, not a hard memory limit.


🔄 Flowing Mode vs Paused Mode

Flowing Mode

  • Uses the data event
  • Data flows automatically
  • Most commonly used

Paused Mode

  • Uses the readable event
  • Data is read manually using stream.read()
  • Gives more control over reading

📦 Buffer vs Stream

One interview question that helped me understand the difference:

Buffer

  • Temporary memory
  • Stores binary data
  • Holds one chunk at a time

Stream

  • Transfers data continuously
  • Processes multiple chunks
  • Better suited for large files

A simple way to remember it:

Buffer stores data. Stream moves data.


🚀 pipeline() vs pipe()

Although pipe() is simple and powerful, Node.js provides pipeline() for production-ready applications.

Why use pipeline()?

  • Better error handling
  • Automatically cleans up streams
  • Prevents resource leaks
  • Recommended for production code

🎯 Interview Takeaways

Today's most important interview concepts:

  • What is a Stream?
  • Why Streams are better than fs.readFile()
  • Readable vs Writable Stream
  • Duplex vs Transform Stream
  • pipe()
  • Backpressure
  • drain event
  • pause() and resume()
  • highWaterMark
  • Flowing vs Paused Mode
  • Buffer vs Stream
  • pipeline()

📚 Key Learning

Streams are one of the core reasons why Node.js is highly efficient for backend development. They allow applications to process large files with minimal memory usage while maintaining excellent performance and scalability.

Understanding Streams, Backpressure, and pipe() has given me a much deeper appreciation of how Node.js handles data under the hood.

Looking forward to learning the HTTP module next! 🚀


If you have any interview tips or real-world use cases for Streams, I'd love to hear them in the comments.

NodeJS #JavaScript #Backend #WebDevelopment #Programming #Coding #100DaysOfCode #OpenSource #Developer #Streams #LearningInPublic

Top comments (0)