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

Stream-based API Rate Limiting

Throttle outgoing stream data to comply with external API rate limits and bandwidth quotas.

In this lesson, you will learn how to throttle outgoing stream data to ensure your application stays within the rate limits or bandwidth quotas of an external API.

The Problem: Flooding the Pipe

When you pipe data to an external API (like a file upload or a log shipping service), the speed of your stream might exceed the API's limits. If you send data too quickly, the server will respond with "429 Too Many Requests" errors or terminate your connection. Since you already understand Backpressure and the drain event, you know that pipe() handles flow control between two internal streams—but it doesn't know anything about external network constraints.

The Solution: Throttling with a Transform Stream

To enforce a rate limit, we can implement a custom Transform stream that acts as a "gatekeeper." Instead of blindly pushing data forward, we track how much data we’ve sent within a specific time window and pause the stream if we hit our quota.

Here is a simplified pattern for limiting throughput:

const { Transform } = require('stream');

class RateLimiter extends Transform {
  constructor(bytesPerSecond) {
    super();
    this.limit = bytesPerSecond;
    this.sentInWindow = 0;
  }

  _transform(chunk, encoding, callback) {
    this.sentInWindow += chunk.length;

    if (this.sentInWindow > this.limit) {
      // Pause incoming data until the next second
      setTimeout(() => {
        this.sentInWindow = 0;
        this.push(chunk);
        callback();
      }, 1000);
    } else {
      this.push(chunk);
      callback();
    }
  }
}

How It Works

By placing this RateLimiter in your pipeline, you create a layer of friction. When _transform detects that the quota is exceeded, it holds the callback execution. Because the source stream is waiting for that callback to be invoked, it effectively stops pushing more data into the pipe. This triggers the backpressure mechanism you’ve already mastered, forcing the entire upstream process to slow down until the setTimeout finishes and we report that we are ready for more data.

Key Takeaway: API rate limiting is achieved by manually delaying the stream’s callback during a transform operation, which signals backpressure upstream and forces the data source to wait for your defined quota window.