Course contentsShow
← Node.js
Lesson 422 of 1,9805. Streams and BackpressureFree lesson

Implementing Backpressure in Network Sockets

Apply flow control techniques to prevent network congestion when streaming data to slow clients.

In this lesson, you will learn how to synchronize data production with consumer consumption speeds to keep your network sockets healthy and performant.

The Problem: The "Slow Client"

When you stream data over a network socket, your server might be capable of reading a file from disk at 500MB/s, but the client on the other end might only have a connection speed of 10MB/s. If you blindly push data into the socket's write buffer, that buffer will grow indefinitely, consuming your server's RAM and potentially causing a crash. This is why we implement backpressure.

Implementing Flow Control

The socket.write() method returns a boolean. If it returns false, it means the underlying kernel buffer is full and you should stop sending data. When the buffer clears, the socket emits a 'drain' event, signaling that it is safe to resume.

Here is how you implement this loop manually:

const fs = require('fs');
const net = require('net');

const server = net.createServer((socket) => {
  const fileStream = fs.createReadStream('large-video.mp4');

  fileStream.on('data', (chunk) => {
    // Attempt to write the chunk
    const canContinue = socket.write(chunk);

    // If the buffer is full, pause the source
    if (!canContinue) {
      fileStream.pause();
    }
  });

  // Resume the source when the socket clears its buffer
  socket.on('drain', () => {
    fileStream.resume();
  });
});

Why this matters

By pausing the fileStream (our data producer), we force the system to stop reading from the disk until the client has caught up. This keeps memory usage constant, regardless of how large the file is or how slow the network connection becomes. Without this check, you would be dumping data into an ever-expanding queue in your application's memory, leading to high latency and system instability. Always respect the return value of write() to ensure your application remains resilient under heavy network load.

Key Takeaway: When writing to a socket, always respect the boolean returned by socket.write(); if it is false, pause your data source and wait for the 'drain' event to resume.