limiter vs rate-limiter-flexible vs ratelimiter vs bottleneck vs express-rate-limit vs p-limit
Rate Limiting Libraries for Node.js
limiterrate-limiter-flexibleratelimiterbottleneckexpress-rate-limitp-limitSimilar Packages:

Rate Limiting Libraries for Node.js

Rate limiting libraries are essential tools in web development that help control the amount of incoming requests to a server or service. They prevent abuse by limiting the number of requests a user can make in a given timeframe, thus protecting resources and ensuring fair usage. These libraries can be used to implement various strategies for rate limiting, such as fixed window, sliding window, token bucket, and leaky bucket algorithms, each suited for different use cases and performance requirements.

Npm Package Weekly Downloads Trend

3 Years

Github Stars Ranking

Stat Detail

Package
Downloads
Stars
Size
Issues
Publish
License
limiter12,674,7151,558158 kB15a year agoMIT
rate-limiter-flexible2,039,6703,521220 kB1314 days agoISC
ratelimiter187,932724-116 years agoMIT
bottleneck01,985-917 years agoMIT
express-rate-limit03,253142 kB1118 days agoMIT
p-limit02,84214.9 kB12 months agoMIT

Feature Comparison: limiter vs rate-limiter-flexible vs ratelimiter vs bottleneck vs express-rate-limit vs p-limit

Configuration Flexibility

  • limiter:

    Limiter has minimal configuration options, focusing on simplicity and ease of use. It is suitable for projects that do not require advanced settings or custom behaviors.

  • rate-limiter-flexible:

    rate-limiter-flexible provides a wide range of configuration options, including different rate limiting strategies and the ability to set limits based on various criteria. This makes it highly adaptable to different use cases.

  • ratelimiter:

    ratelimiter offers basic configuration options, making it easy to set up but lacking the advanced flexibility found in more complex libraries.

  • bottleneck:

    Bottleneck offers extensive configuration options, allowing developers to customize limits based on various criteria such as user ID, request type, or time intervals. This flexibility makes it suitable for applications with diverse rate limiting needs.

  • express-rate-limit:

    express-rate-limit provides basic configuration options such as windowMs and max, but is less flexible compared to Bottleneck. It is designed for straightforward use cases where complex configurations are not necessary.

  • p-limit:

    p-limit allows you to set the maximum number of concurrent promises, providing a straightforward way to manage asynchronous operations, but does not offer extensive configuration options beyond concurrency limits.

Integration with Frameworks

  • limiter:

    Limiter is framework-agnostic and can be used in any Node.js application, but it does not offer specific integrations with popular frameworks.

  • rate-limiter-flexible:

    rate-limiter-flexible can be integrated with various Node.js frameworks and supports multiple storage backends, making it suitable for complex applications that require flexibility in implementation.

  • ratelimiter:

    ratelimiter is a simple library that can be used in any Node.js application but does not provide specific integrations with frameworks.

  • bottleneck:

    Bottleneck can be integrated into various frameworks and libraries, making it versatile for different types of applications beyond just web servers, including background jobs and API clients.

  • express-rate-limit:

    express-rate-limit is specifically designed for Express.js applications, providing seamless integration as middleware, which simplifies implementation for Express developers.

  • p-limit:

    p-limit is a standalone utility that can be used in any JavaScript environment, making it versatile for various applications, but it does not provide framework-specific features.

Performance

  • limiter:

    Limiter is lightweight and performs well for simple rate limiting tasks, making it suitable for applications with low to moderate traffic.

  • rate-limiter-flexible:

    rate-limiter-flexible is designed for high performance and can handle large volumes of requests efficiently, especially when using Redis or other optimized storage backends.

  • ratelimiter:

    ratelimiter is simple and performs adequately for basic rate limiting tasks, but may not be suitable for high-performance applications.

  • bottleneck:

    Bottleneck is optimized for performance, allowing for efficient management of concurrent requests and minimizing the overhead associated with rate limiting. It is suitable for high-throughput applications.

  • express-rate-limit:

    express-rate-limit is efficient for basic rate limiting needs but may introduce some overhead in high-traffic applications due to its middleware nature.

  • p-limit:

    p-limit is designed to manage concurrency effectively, ensuring that performance remains optimal even when limiting the number of concurrent operations.

Use Cases

  • limiter:

    Limiter is suitable for simple applications that require basic rate limiting without additional features, such as limiting requests to a single endpoint.

  • rate-limiter-flexible:

    rate-limiter-flexible is designed for applications with complex rate limiting needs, such as e-commerce platforms or social media applications that require dynamic rate limits based on user behavior.

  • ratelimiter:

    ratelimiter is suitable for applications that require basic rate limiting without the need for advanced features or configurations.

  • bottleneck:

    Bottleneck is ideal for applications that require complex rate limiting scenarios, such as API clients that need to respect rate limits imposed by third-party services while managing multiple requests concurrently.

  • express-rate-limit:

    express-rate-limit is best suited for web applications that need to limit requests from users to prevent abuse, such as login attempts or API calls.

  • p-limit:

    p-limit is perfect for managing concurrent asynchronous operations, such as making multiple API calls or processing large datasets without overwhelming the server.

Learning Curve

  • limiter:

    Limiter is straightforward and easy to understand, making it suitable for developers who need quick implementation without complex configurations.

  • rate-limiter-flexible:

    rate-limiter-flexible has a steeper learning curve due to its advanced features and configurations, but it offers comprehensive documentation to help users understand its capabilities.

  • ratelimiter:

    ratelimiter is simple to use, with a low learning curve, making it accessible for developers of all skill levels.

  • bottleneck:

    Bottleneck has a moderate learning curve due to its extensive features and configuration options, but it provides detailed documentation to assist developers.

  • express-rate-limit:

    express-rate-limit is easy to learn and implement, especially for developers familiar with Express.js, making it a great choice for beginners.

  • p-limit:

    p-limit has a simple API, making it easy to learn for developers familiar with promises and asynchronous programming in JavaScript.

How to Choose: limiter vs rate-limiter-flexible vs ratelimiter vs bottleneck vs express-rate-limit vs p-limit

  • limiter:

    Opt for Limiter if you require a lightweight solution that provides basic rate limiting features without additional dependencies. It is suitable for applications that need minimal setup and straightforward functionality.

  • rate-limiter-flexible:

    Choose rate-limiter-flexible if you need a powerful and flexible rate limiting solution that supports various storage backends (like Redis, MongoDB, etc.) and advanced features such as different rate limiting strategies and dynamic limits. It is ideal for applications with complex rate limiting requirements.

  • ratelimiter:

    Select ratelimiter for a simple and effective rate limiting solution that is easy to implement. It is suitable for applications that require basic rate limiting without the overhead of more complex libraries.

  • bottleneck:

    Choose Bottleneck if you need a highly configurable and flexible rate limiter that allows for complex scheduling and prioritization of tasks. It is ideal for managing concurrent requests and can handle both rate limiting and queuing effectively.

  • express-rate-limit:

    Select express-rate-limit if you are building an Express.js application and need a straightforward middleware solution for basic rate limiting. It is easy to set up and integrates seamlessly with Express, making it suitable for simple use cases.

  • p-limit:

    Use p-limit when you need to limit the number of concurrent promises in your application. This is particularly useful for managing asynchronous operations and ensuring that your application does not overwhelm resources with too many simultaneous requests.

README for limiter

limiter

Build Status NPM Downloads

Provides a generic rate limiter for the web and node.js. Useful for API clients, web crawling, or other tasks that need to be throttled. Two classes are exposed, RateLimiter and TokenBucket. TokenBucket provides a lower level interface to rate limiting with a configurable burst rate and drip rate. RateLimiter sits on top of the token bucket and adds a restriction on the maximum number of tokens that can be removed each interval to comply with common API restrictions such as "150 requests per hour maximum".

Installation

yarn add limiter

Usage

A simple example allowing 150 requests per hour:

import { RateLimiter } from "limiter";

// Allow 150 requests per hour (the Twitter search limit). Also understands
// 'second', 'minute', 'day', or a number of milliseconds
const limiter = new RateLimiter({ tokensPerInterval: 150, interval: "hour" });

async function sendRequest() {
  // This call will throw if we request more than the maximum number of requests
  // that were set in the constructor
  // remainingRequests tells us how many additional requests could be sent
  // right this moment
  const remainingRequests = await limiter.removeTokens(1);
  callMyRequestSendingFunction(...);
}

Another example allowing one message to be sent every 250ms:

import { RateLimiter } from "limiter";

const limiter = new RateLimiter({ tokensPerInterval: 1, interval: 250 });

async function sendMessage() {
  const remainingMessages = await limiter.removeTokens(1);
  callMyMessageSendingFunction(...);
}

The default behaviour is to wait for the duration of the rate limiting that's currently in effect before the promise is resolved, but if you pass in "fireImmediately": true, the promise will be resolved immediately with remainingRequests set to -1:

import { RateLimiter } from "limiter";

const limiter = new RateLimiter({
  tokensPerInterval: 150,
  interval: "hour",
  fireImmediately: true
});

async function requestHandler(request, response) {
  // Immediately send 429 header to client when rate limiting is in effect
  const remainingRequests = await limiter.removeTokens(1);
  if (remainingRequests < 0) {
    response.writeHead(429, {'Content-Type': 'text/plain;charset=UTF-8'});
    response.end('429 Too Many Requests - your IP is being rate limited');
  } else {
    callMyMessageSendingFunction(...);
  }
}

A synchronous method, tryRemoveTokens(), is available in both RateLimiter and TokenBucket. This will return immediately with a boolean value indicating if the token removal was successful.

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');

To get the number of remaining tokens outside the removeTokens promise, simply use the getTokensRemaining method.

import { RateLimiter } from "limiter";

const limiter = new RateLimiter({ tokensPerInterval: 1, interval: 250 });

// Prints 1 since we did not remove a token and our number of tokens per
// interval is 1
console.log(limiter.getTokensRemaining());

Using the token bucket directly to throttle at the byte level:

import { TokenBucket } from "limiter";

const BURST_RATE = 1024 * 1024 * 150; // 150KB/sec burst rate
const FILL_RATE = 1024 * 1024 * 50; // 50KB/sec sustained rate

// We could also pass a parent token bucket in to create a hierarchical token
// bucket
// bucketSize, tokensPerInterval, interval
const bucket = new TokenBucket({
  bucketSize: BURST_RATE,
  tokensPerInterval: FILL_RATE,
  interval: "second"
});

async function handleData(myData) {
  await bucket.removeTokens(myData.byteLength);
  sendMyData(myData);
}

Additional Notes

Both the token bucket and rate limiter should be used with a message queue or some way of preventing multiple simultaneous calls to removeTokens(). Otherwise, earlier messages may get held up for long periods of time if more recent messages are continually draining the token bucket. This can lead to out of order messages or the appearance of "lost" messages under heavy load.

License

MIT License