Installations
npm install redis-sliding-rate-limiter
Developer Guide
Typescript
Yes
Module System
CommonJS
Min. Node Version
>=12.20.0
Node Version
14.21.3
NPM Version
6.14.18
Releases
Unable to fetch releases
Contributors
Unable to fetch Contributors
Languages
TypeScript (95.2%)
JavaScript (4.8%)
Developer
spinlud
Download Statistics
Total Downloads
75,246
Last Day
154
Last Week
534
Last Month
2,447
Last Year
32,914
GitHub Statistics
8 Stars
63 Commits
1 Forks
3 Watching
1 Branches
1 Contributors
Bundle Size
15.32 kB
Minified
3.58 kB
Minified + Gzipped
Package Meta Information
Latest Version
6.0.0
Package Id
redis-sliding-rate-limiter@6.0.0
Unpacked Size
119.35 kB
Size
22.69 kB
File Count
46
NPM Version
6.14.18
Node Version
14.21.3
Publised On
29 Nov 2023
Total Downloads
Cumulative downloads
Total Downloads
75,246
Last day
90.1%
154
Compared to previous day
Last week
-0.9%
534
Compared to previous week
Last month
35.9%
2,447
Compared to previous month
Last year
39.1%
32,914
Compared to previous year
Daily Downloads
Weekly Downloads
Monthly Downloads
Yearly Downloads
redis-sliding-rate-limiter
Flexible and performant rate limiter, supporting a sliding window algorithm with arbitrary precision. Compatible with two popular Redis clients: redis, ioredis.
Table of Contents
Why another rate limiter?
Naive rate limiter algorithms suffer from a well known problem where a burst of requests at the window boundary will cause the limiter allowing more requests than what is expected for a particular key. For example, with a limit of 100 requests per minute, a client could send 100 requests in the last second of the first minute and another 100 requests in the first second of the second minute, resulting in 200 accepted requests in 2 seconds. This library supports a flexible sliding window algorithm based on Redis backend which solves this problem efficiently. The main features are the following:
- Limiter window can be defined with arbitrary size and precision, from years down to milliseconds (e.g. a window of 3 seconds with decisecond precision or a window of 5 minutes with second precision).
- Fast (average of 0.08 ms).
- Each request is added to the current window with microsecond precision, avoiding losing count of concurrent requests for a particular key.
- Redis server clock is used as the single source of truth for any time calculation.
- For each request, expiration timestamps of the current window and the first element in that window are returned to the client. This means that the client can know precisely when a free slot will be available or when the window will be empty.
- Express compatible middleware with customizable status code, messages and response headers.
- Compatible with two popular Redis clients: redis, ioredis.
- Zero dependencies.
Installation
Install package:
1npm install --save redis-sliding-rate-limiter
Usage
1const { createClient } = require('redis'); 2const { RateLimiter, Unit } = require('redis-sliding-rate-limiter'); 3 4(async () => { 5 const client = createClient({ 6 url: `redis://localhost:6379`, 7 }); 8 9 await client.connect(); 10 11 // 10 requests every 3 seconds, with decisecond precision. Allow 10% of requests to exceed the limit. 12 const limiter = new RateLimiter({ 13 client: client, 14 window: { 15 unit: Unit.SECOND, 16 size: 3, 17 subdivisionUnit: Unit.DECISECOND, // Defines with which precision elements would expire in the current window 18 }, 19 limit: 10, 20 limitOverhead: 0.1, // Fraction of requests that can exceed the limit, rounded down (10 * 0.1 = 1 in this example) 21 }); 22 23 const key = 'OneRing'; 24 25 const results = await Promise.all([ 26 limiter.get(key), // 1 27 limiter.get(key), // 2 28 limiter.get(key), // 3 29 limiter.get(key), // 4 30 limiter.get(key), // 5 31 limiter.get(key), // 6 32 limiter.get(key), // 7 33 limiter.get(key), // 8 34 limiter.get(key), // 9 35 limiter.get(key), // 10 36 limiter.get(key), // 11 - Expect to succeed thanks to overhead 37 limiter.get(key), // 12 - Expect to fail 38 ]); 39 40 for (const res of results) { 41 const { allowed, remaining, firstExpireAtMs, windowExpireAtMs } = res; 42 console.log(allowed, remaining, firstExpireAtMs, windowExpireAtMs); 43 } 44 45 // Output: 46 // 47 // true 9 1610466521278 1610466521278 48 // true 8 1610466521278 1610466521278 49 // true 7 1610466521278 1610466521279 50 // true 6 1610466521278 1610466521279 51 // true 5 1610466521278 1610466521279 52 // true 4 1610466521278 1610466521279 53 // true 3 1610466521278 1610466521279 54 // true 2 1610466521278 1610466521279 55 // true 1 1610466521278 1610466521279 56 // true 0 1610466521278 1610466521279 57 // true 0 1610466521278 1610466521279 58 // false 0 1610466521278 1610466521279 59 60 client.quit(); 61})();
Express middleware
The library exposes a configurable middleware factory that you can use directly in your
Express application.
See the following example:
1const express = require('express');
2const Redis = require('ioredis');
3const { RateLimiter, Unit, createExpressMiddleware } = require('redis-sliding-rate-limiter');
4
5(async () => {
6 const app = express();
7
8 const client = new Redis({
9 host: 'localhost',
10 port: 6379
11 });
12
13 const middleware = createExpressMiddleware({
14 // Define limiters that will be evaluated from this middleware for each request
15 limiters: [
16 {
17 limiter: new RateLimiter({
18 client: client,
19 window: {
20 unit: Unit.SECOND,
21 size: 1,
22 },
23 limit: 5,
24 }),
25 overrideKey: true,
26 // Compute Redis key from request and limiter objects. Can also be defined at middleware level (see below).
27 overrideKeyFn: (req, limiter) => {
28 return req.path + limiter.name;
29 },
30 key: 'This key will be overridden',
31 errorMessage: '[Peak] Too many requests',
32 },
33 {
34 limiter: new RateLimiter({
35 client: client,
36 window: {
37 unit: Unit.HOUR,
38 size: 1,
39 subdivisionUnit: Unit.MINUTE,
40 },
41 limit: 10000, // This will be overridden
42 }),
43 overrideLimit: true,
44 // Override limit if enabled. Can also be defined at middleware level (see below).
45 overrideLimitFn: (req, limiter) => {
46 return parseInt(req.query.limit); // Make sure this function returns a positive integer...
47 },
48 // Optional function to skip request evaluation for a specific limiter. Should return true if the evaluation must be skipped, false otherwise.
49 skipFn: (req, limiter) => {
50 return false;
51 },
52 errorMessage: '[Hourly] Too many requests',
53 },
54 ],
55
56 // Middleware level key override.
57 // Fallback in case a limiter does not provide a overrideKeyFn function and has overrideKey enabled.
58 overrideKeyFn: (req, limiter) => {
59 return 'some key';
60 },
61
62 // Middleware level limit override.
63 // Fallback in case a limiter does not provide a overrideLimitFn function and has overrideLimit enabled.
64 overrideLimitFn: (req, limiter) => {
65 return 666;
66 },
67
68 // Error status code
69 errorStatusCode: 429,
70
71 // Enable/disable setting headers on response
72 setHeaders: true,
73
74 // Custom function to set headers on response object (otherwise default headers will be used)
75 setHeadersFn: (req, res, limiter, limiterResponse) => {
76 const {remaining, firstExpireAtMs, windowExpireAtMs} = limiterResponse;
77 res.set(remainingH, '' + remaining);
78 res.set(firstExpireH, '' + firstExpireAtMs);
79 res.set(resetH, '' + windowExpireAtMs);
80 },
81
82 // Skip (whitelist) requests. Should return true if the request must be skipped, false otherwise
83 skip: (req) => {
84 return req.pleaseSkipMe;
85 },
86
87 // Function called when a request is throttled (not allowed)
88 onThrottleRequest: (req, res, key) => {
89 return res.status(429).send(`Too many requests for key ${key}`);
90 }
91 });
92
93 // Plug-in the middleware
94 app.use(middleware);
95
96 app.get('/', (req, res) => {
97 return res.send('Yo!');
98 });
99
100 app.listen(8080, () => console.log('Server listening on port 8080...'));
101})();
License
No vulnerabilities found.
Reason
no dangerous workflow patterns detected
Reason
no binaries found in the repo
Reason
no SAST tool detected
Details
- Warn: no pull requests merged into dev branch
Reason
detected GitHub workflow tokens with excessive permissions
Details
- Warn: no topLevel permission defined: .github/workflows/ci.yml:1
- Info: no jobLevel write permissions found
Reason
0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0
Reason
Found 0/30 approved changesets -- score normalized to 0
Reason
dependency not pinned by hash detected -- score normalized to 0
Details
- Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yml:24: update your workflow using https://app.stepsecurity.io/secureworkflow/spinlud/redis-sliding-rate-limiter/ci.yml/master?enable=pin
- Warn: npmCommand not pinned by hash: .github/workflows/ci.yml:28
- Info: 0 out of 1 GitHub-owned GitHubAction dependencies pinned
- Info: 0 out of 1 npmCommand dependencies pinned
Reason
no effort to earn an OpenSSF best practices badge detected
Reason
security policy file not detected
Details
- Warn: no security policy file detected
- Warn: no security file to analyze
- Warn: no security file to analyze
- Warn: no security file to analyze
Reason
project is not fuzzed
Details
- Warn: no fuzzer integrations found
Reason
license file not detected
Details
- Warn: project does not have a license file
Reason
branch protection not enabled on development/release branches
Details
- Warn: branch protection not enabled for branch 'master'
Reason
11 existing vulnerabilities detected
Details
- Warn: Project is vulnerable to: GHSA-qwcr-r2fm-qrc7
- Warn: Project is vulnerable to: GHSA-grv7-fg5c-xmjg
- Warn: Project is vulnerable to: GHSA-pxg6-pf52-xh8x
- Warn: Project is vulnerable to: GHSA-3xgq-45jj-v275
- Warn: Project is vulnerable to: GHSA-rv95-896h-c2vc
- Warn: Project is vulnerable to: GHSA-qw6h-vgh9-j6wx
- Warn: Project is vulnerable to: GHSA-952p-6rrq-rcjv
- Warn: Project is vulnerable to: GHSA-9wv6-86v2-598j
- Warn: Project is vulnerable to: GHSA-rhx6-c78j-4q9w
- Warn: Project is vulnerable to: GHSA-m6fv-jmcg-4jfg
- Warn: Project is vulnerable to: GHSA-cm22-4g7w-348p
Score
2.2
/10
Last Scanned on 2025-01-27
The Open Source Security Foundation is a cross-industry collaboration to improve the security of open source software (OSS). The Scorecard provides security health metrics for open source projects.
Learn MoreOther packages similar to redis-sliding-rate-limiter
sliding-window-rate-limiter
Sliding window rate limiter with Redis 3.2 backend
advance-rate-limiter
A customizable rate limiter middleware for Express.js applications using Redis and sliding window algorithm.
redis-rolling-rate-limiter
Rolling Rate Limiter is a module for Node.js which provides a basic, but a solid rate limiter using sliding windows stored in Redis.
redis-ratelimit
Rate limiter using redis - sliding window based on sorted sets and fixed window