Course contentsShow
← Node.js
Lesson 376 of 1,9804. I/O and File System OperationsFree lesson

Asynchronous Batching of Write Operations

Group multiple small write operations into larger chunks to maximize disk I/O throughput.

In this lesson, you’ll learn how to significantly boost disk I/O performance by grouping many small write operations into a single, larger chunk.

Why Batching Matters

Every time you perform a write operation to the disk, the operating system performs several expensive tasks: it translates your request, manages file system metadata, and interacts with the physical storage hardware. If you write one byte at a time, your code spends more time waiting for the "handshake" between the CPU and the disk than actually moving data.

By implementing asynchronous batching, we buffer data in memory and only trigger a system write once a specific size threshold (a "chunk") is reached or a timer expires.

The Implementation Strategy

Instead of writing immediately, you append incoming data into a Buffer or a queue. Once that buffer hits a pre-defined size (e.g., 64KB), you perform one single fs.write() operation.

Here is how you might visualize this logic:

let writeBuffer = Buffer.alloc(0);
const BATCH_SIZE = 65536; // 64KB

function processIncomingData(chunk) {
  // Combine existing buffer with new data
  writeBuffer = Buffer.concat([writeBuffer, chunk]);

  // If we have enough data, perform a single bulk write
  if (writeBuffer.length >= BATCH_SIZE) {
    const dataToWrite = writeBuffer;
    writeBuffer = Buffer.alloc(0); // Reset buffer
    
    fs.write(fd, dataToWrite, (err) => {
      if (err) console.error("Write failed");
    });
  }
}

Balancing Throughput and Latency

There is a trade-off here. While waiting to fill a 64KB buffer maximizes throughput, it increases the latency of individual write operations. If your application requires data to be flushed even if the buffer isn't full, you should implement a setTimeout to ensure that data waiting in the buffer is eventually written to disk after a set duration, even if the "batch" isn't technically complete yet.

This pattern is fundamental for high-performance systems like logging agents or database engines, where disk head movement or system call overhead can become the primary bottleneck.

Key Takeaway: Instead of hammering the disk with frequent small writes, aggregate data in memory and perform bulk writes to drastically reduce system call overhead and improve I/O throughput.