New:Introducing Socket Scanning for VS Code Marketplace Extensions.Learn more →
Get Started

flex-rate-limit

Package Overview
Dependencies
Maintainers
1
Versions
15
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

flex-rate-limit

Universal rate limiting module for Node.js - supports any framework, multiple storage backends, flexible algorithms

Source
npmnpm
Version
2.2.2
Version published
Weekly downloads
38
-44.93%
Maintainers
1
Weekly downloads
 
Created
Source

flex-rate-limit

A framework-agnostic Node.js rate limiting library with multiple algorithms, Memory / Redis / cache-hub backed storage, and Express-style middleware.

npm version License: Apache-2.0 Node.js Version

Why Use It

  • Framework-agnostic core: call check() from Express, Koa, Egg.js, Hapi, Fastify, workers, queues, or any custom adapter.
  • Express-style middleware: use limiter.middleware() directly in Express-compatible stacks.
  • Four algorithms: sliding window, fixed window, token bucket, and leaky bucket.
  • Multiple stores: in-memory storage, Redis storage, CacheHubStore, or your own store adapter.
  • Distributed-ready options: use Redis or cache-hub Redis atomic backends when counters must be shared across instances.
  • Standard metadata: each check returns allowed, limit, current, remaining, resetTime, and retryAfter.
  • Type definitions included: CommonJS, ESM, and TypeScript consumers are supported.

Requirements

  • Node.js >=18.0.0
  • npm, pnpm, or another package manager compatible with the npm registry
  • Redis is optional and only needed for Redis-backed distributed rate limiting

Installation

npm install flex-rate-limit

Redis-backed usage:

npm install flex-rate-limit ioredis

cache-hub atomic backend usage:

npm install flex-rate-limit cache-hub ioredis

Quick Start

Direct check()

const { RateLimiter } = require('flex-rate-limit');

const limiter = new RateLimiter({
  windowMs: 15 * 60 * 1000,
  max: 100,
});

const result = await limiter.check('user:123');

if (!result.allowed) {
  console.log(`Retry after ${result.retryAfter} ms`);
}

Express Middleware

const express = require('express');
const { RateLimiter } = require('flex-rate-limit');

const app = express();

const globalLimiter = new RateLimiter({
  windowMs: 15 * 60 * 1000,
  max: 100,
});

app.use(globalLimiter.middleware());

const loginLimiter = new RateLimiter({
  windowMs: 15 * 60 * 1000,
  max: 5,
});

app.post('/api/login', loginLimiter.middleware(), (_req, res) => {
  res.json({ message: 'login accepted' });
});

app.listen(3000);

Koa, Egg.js, Hapi, Fastify, and Other Frameworks

Use check() and map the result to the framework's own middleware, hook, or pre-handler shape:

const { RateLimiter } = require('flex-rate-limit');

const limiter = new RateLimiter({
  windowMs: 60 * 1000,
  max: 60,
});

async function guard(ctx, next) {
  const key = `user:${ctx.user?.id || ctx.ip}:${ctx.path}`;
  const result = await limiter.check(key, { route: ctx.path });

  if (!result.allowed) {
    ctx.status = 429;
    ctx.body = { error: 'Too Many Requests', retryAfter: result.retryAfter };
    return;
  }

  await next();
}

See the runnable framework examples in examples/ and the quickstart guide in docs/getting-started/quickstart.md.

Storage Backends

Memory Store

The default store is fast and simple. Use it for single-process services, local development, tests, and cases where counters do not need to be shared across instances.

const limiter = new RateLimiter({
  windowMs: 60 * 1000,
  max: 100,
  store: 'memory',
});

RedisStore

Use RedisStore when multiple application instances must share counters.

const Redis = require('ioredis');
const { RateLimiter, RedisStore } = require('flex-rate-limit');

const redis = new Redis(process.env.REDIS_URL || 'redis://127.0.0.1:6379');

const limiter = new RateLimiter({
  windowMs: 60 * 1000,
  max: 100,
  store: new RedisStore({ client: redis, prefix: 'rl:' }),
});

CacheHubStore

CacheHubStore keeps flex-rate-limit as the algorithm and middleware layer while delegating high-concurrency state updates to cache-hub atomic primitives. Pass a Redis client for distributed production usage; omit the client only when an in-memory cache-hub backend is acceptable.

const Redis = require('ioredis');
const { RateLimiter, CacheHubStore } = require('flex-rate-limit');

const redis = new Redis(process.env.REDIS_URL || 'redis://127.0.0.1:6379');

const limiter = new RateLimiter({
  algorithm: 'sliding-window',
  windowMs: 60 * 1000,
  max: 100,
  store: new CacheHubStore({ client: redis, prefix: 'rl:' }),
});

Read more in the storage guide.

Algorithms

AlgorithmBest ForNotes
sliding-windowPrecise rolling limitsDefault algorithm; stores more per-key state
fixed-windowHigh-throughput coarse windowsFast, but requests can cluster around window boundaries
token-bucketControlled burstsAllows bursts up to capacity and refills over time
leaky-bucketSmoothing trafficDrains at a steady rate

Choose semantics first, then optimize storage and hot paths. See algorithm comparison and deep analysis.

Common Configuration

const limiter = new RateLimiter({
  windowMs: 60 * 1000,
  max: 100,
  algorithm: 'sliding-window',
  headers: true,
  keyGenerator: (req) => `user:${req.user?.id || req.ip}:${req.path}`,
  skip: (req) => req.path === '/health',
  handler: (req, res) => {
    res.status(429).json({ error: 'Too Many Requests' });
  },
  perRoute: {
    '/api/login': { max: 5, windowMs: 15 * 60 * 1000 },
    '/api/users': { max: 100, windowMs: 60 * 1000 },
  },
});
OptionDefaultDescription
windowMs60000Time window in milliseconds
max100Max requests per window; may be a function
algorithmsliding-windowOne of the four supported algorithms
storememoryStore instance or 'memory'
keyGeneratorIP-basedBuilds the rate-limit key from request context
skip() => falseReturn true to bypass rate limiting
handlerbuilt-in 429 responseCustom over-limit handler
headerstrueWrite X-RateLimit-* and Retry-After headers
perRoutenullRoute-specific overrides
skipSuccessfulRequestsfalseRoll back successful responses
skipFailedRequestsfalseRoll back failed responses

Full details are in the configuration guide and API reference.

Result Shape

{
  allowed: true,
  limit: 100,
  current: 1,
  remaining: 99,
  resetTime: 1767225600000,
  retryAfter: 0
}

Benchmarks

The repository includes reproducible local benchmark scripts for Memory direct checks, Redis direct checks, and HTTP middleware scenarios.

Run these from a cloned repository after installing development dependencies:

npm install
npm run benchmark:memory
npm run benchmark:redis
npm run benchmark:http

The npm runtime package does not require benchmark dependencies. Redis and HTTP benchmark output records the Node.js version, Redis URL, key distribution, concurrency, and other parameters. Use BENCH_JSON=1 when you need machine-readable output.

See Benchmark and Performance for commands, environment variables, and interpretation notes.

Documentation

EntryDescription
Documentation indexFull documentation navigation
QuickstartFirst integration path and framework examples
ConfigurationComplete option reference and practical presets
StorageMemory, Redis, and CacheHubStore selection
Business lock guideUser + route scoped rate limiting
Algorithm comparisonChoosing the right algorithm
API referenceClasses, options, stores, and exports
Benchmark guideLocal benchmark commands and caveats

The website is built with Rspress and reuses the docs/ directory:

npm run docs:dev
npm run docs:build

Examples

Runnable examples are available in examples/:

CategoryFiles
Quickstartquickstart-express.js, quickstart-koa.js, quickstart-egg.js, quickstart-hapi.js, quickstart-fastify.js
Router examplesexpress-router-example.js, koa-router-example.js, egg-router-example.js, fastify-router-example.js
IP whitelist examplesexpress-ip-whitelist-independent.js, koa-ip-whitelist-independent.js, ip-whitelist-example.js
Standalone usagestandalone-example.js
Business lockegg-business-lock-example.js

Development

npm test
npm run test:unit
npm run test:integration
npm run typecheck
npm run lint
npm run coverage

Troubleshooting

  • Counters are not shared across instances: use RedisStore or CacheHubStore with a Redis client instead of the default Memory store.
  • Redis benchmarks are skipped: start Redis locally or set REDIS_URL / BENCH_REDIS_URL.
  • Package installs but Redis code fails at runtime: install and configure a Redis client such as ioredis.
  • Koa/Fastify/Hapi integration feels awkward: call check() directly and wrap the result in the framework's native middleware or hook style.
  • Benchmark numbers differ from the docs or CI: local CPU, Node.js version, Redis latency, key distribution, and HTTP app work all affect throughput.

Support

License

Apache-2.0

Keywords

rate-limit

FAQs

Package last updated on 09 Jun 2026

Related posts