limiter

repository·main·Indexed 23 days ago

https://github.com/jhurliman/node-rate-limiter

A generic rate limiter for Node.js and web environments, version 3.0.0. It provides a high-level RateLimiter class for complying with API restrictions and a low-level TokenBucket class for granular throttling, such as byte-level control. Features include asynchronous token removal with waiting, synchronous non-blocking checks via tryRemoveTokens(), and support for hierarchical rate limiting through parent buckets.

Tokens
2.3K
Snippets
5
Records
16
Agent score
81%

What's inside limiter

  1. How RateLimiter and TokenBucket work together

    main

    The library provides two main classes for rate limiting:

    1. TokenBucket: A lower-level interface that uses a configurable burst rate and drip rate. It is useful for scenarios like byte-level throttling.
    2. RateLimiter: A higher-level abstraction built on top of TokenBucket. It is designed to comply with common API restrictions (e.g., "150 requests per hour") by adding a restriction on the maximum number of tokens that can be removed each interval.

    When using these classes, it is recommended to use them with a message queue to prevent multiple simultaneous calls to removeTokens(). Without a queue, earlier messages might be held up for long periods if newer messages continually drain the bucket, potentially causing out-of-order or seemingly "lost" messages.

  2. Check remaining tokens synchronously with tryRemoveTokens()

    main

    Both RateLimiter and TokenBucket provide a synchronous method tryRemoveTokens(tokens). This method returns immediately with a boolean: true if the tokens were successfully removed, or false if they were not.

    import { RateLimiter } from "limiter";
    
    const limiter = new RateLimiter({ tokensPerInterval: 10, interval: "second" });
    
    if (limiter.tryRemoveTokens(5)) {
      console.log('Tokens removed');
    } else {
      console.log('No tokens removed');
    }
  3. Use TokenBucket for low-level throttling

    main

    Use TokenBucket for more granular control, such as throttling data at the byte level. It allows you to define a bucketSize (burst capacity) and a tokensPerInterval (sustained drip rate).

    Configuration Options:

    • bucketSize: The maximum number of tokens the bucket can hold (burst capacity).
    • tokensPerInterval: The number of tokens added to the bucket per interval.
    • interval: The duration of the interval (e.g., 'second', 'minute', or milliseconds).
    import { TokenBucket } from "limiter";
    
    const BURST_RATE = 1024 * 1024 * 150; // 150KB/sec burst rate
    const FILL_RATE = 1024 * 1024 * 50; // 50KB/sec sustained rate
    
    const bucket = new TokenBucket({
      bucketSize: BURST_RATE,
      tokensPerInterval: FILL_RATE,
      interval: "second"
    });
    
    async function handleData(myData) {
      await bucket.removeTokens(myData.byteLength);
      sendMyData(myData);
    }
  4. Use RateLimiter to enforce request limits

    main

    Use RateLimiter to restrict the number of actions allowed within a specific time interval.

    Configuration Options:

    • tokensPerInterval: The number of tokens allowed per interval.
    • interval: The duration of the interval. Accepts 'second', 'minute', 'day', or a number representing milliseconds.
    • fireImmediately (optional): If set to true, the removeTokens promise resolves immediately. If tokens are unavailable, it returns -1 instead of waiting. This is useful for returning 429 Too Many Requests responses immediately in web servers.
    import { RateLimiter } from "limiter";
    
    // Allow 150 requests per hour
    const limiter = new RateLimiter({ tokensPerInterval: 150, interval: "hour" });
    
    async function sendRequest() {
      // Returns the number of additional requests that could be sent right now
      const remainingRequests = await limiter.removeTokens(1);
      callMyRequestSendingFunction(...);
    }
  5. Get the current number of remaining tokens

    main

    To check how many tokens are currently available without triggering the waiting behavior of removeTokens(), use the getTokensRemaining() method.

    import { RateLimiter } from "limiter";
    
    const limiter = new RateLimiter({ tokensPerInterval: 1, interval: 250 });
    
    // Returns the current count of available tokens
    console.log(limiter.getTokensRemaining());
  6. Configure the RateLimiter class

    main

    The RateLimiter class manages request intervals using a token bucket mechanism. When initializing, you must provide a RateLimiterOpts object.

    Options:

    • tokensPerInterval (number): The maximum number of tokens that can be removed at any given moment and over the course of one interval.
    • interval (Interval): The interval length. This can be a number representing milliseconds, or one of the following strings: 'second', 'minute', 'hour', or 'day'.
    • fireImmediately (boolean, optional): If true, the removeTokens method will resolve immediately (returning -1) when rate limiting is in effect. If false (default), it will wait until enough tokens become available.
  7. Use the RateLimiter class

    main
    The RateLimiter class is the primary interface for controlling the rate of operations. It is exported from the main entry point. To use it, you typically instantiate it with a specific strategy (like a TokenBucket) to manage how many requests or operations are allowed over a period of time.
  8. Use tryRemoveTokens() for non-blocking checks

    main

    The tryRemoveTokens(count: number) method attempts to remove tokens without waiting. It is useful for logic that needs to skip an action rather than queue it.

    • Returns true: If the tokens were successfully removed.
    • Returns false: If the request exceeds the maximum allowed tokens or if the interval limit has already been reached.
  9. Configure a TokenBucket

    main

    The TokenBucket class implements a hierarchical token bucket algorithm for rate limiting. You can instantiate it by passing a TokenBucketOpts object.

    Configuration Options

    OptionTypeDescription
    bucketSizenumberThe maximum number of tokens the bucket can hold (the burst rate). Set to 0 for an infinite bucket.
    tokensPerIntervalnumberThe number of tokens added to the bucket over the duration of the interval.
    intervalnumber | stringThe time duration for the token drip. Accepts milliseconds as a number, or the following strings: 'second', 'sec', 'minute', 'min', 'hour', 'hr', 'day'.
    parentBucketTokenBucket(Optional) A parent bucket that this bucket must also consume tokens from, enabling hierarchical rate limiting.