redis-lua-rate-limiter 1.0.0 โ†’ 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/README.md +225 -37
  2. package/package.json +5 -4
package/README.md CHANGED
@@ -1,24 +1,100 @@
1
- # redis-lua-rate-limiter
2
1
 
3
- Distributed, atomic, token-bucket rate limiter for Node.js powered by Redis Lua scripts.
2
+ ### Redis-lua-rate-limiter
4
3
 
5
- ## Why?
4
+ **Distributed, atomic, token-bucket rate limiter for Node.js powered by Redis Lua scripts.**
6
5
 
7
- Most Express rate limiters break in distributed systems.
8
- This one keeps the logic inside Redis using Lua for atomic safety.
6
+ > Works correctly across multiple Node.js instances with zero race conditions by keeping the rate-limiting logic inside Redis.
9
7
 
10
- ## Install
8
+ ---
9
+
10
+ ## The Problem With Typical Express Rate Limiters
11
+
12
+ Most middleware like `express-rate-limit`:
13
+
14
+ * Store counters in memory
15
+ * Break when you scale to multiple servers
16
+ * Leak requests under concurrency
17
+ * Suffer from race conditions
18
+
19
+ This library solves that by:
20
+
21
+ > Running the entire rate limiting algorithm **inside Redis** using **Lua**, executed atomically.
22
+
23
+ ---
24
+
25
+ ## What is the Token Bucket Algorithm?
26
+
27
+ Token Bucket is an industry standard algorithm used by:
28
+
29
+ * API Gateways
30
+ * CDNs
31
+ * Reverse Proxies
32
+ * Cloud providers
33
+
34
+ ### How it works
35
+
36
+ Each user / API key / IP has a **bucket**:
37
+
38
+ * Bucket has **capacity** (max tokens)
39
+ * Tokens **refill over time**
40
+ * Each request **consumes 1 token**
41
+ * If bucket is empty โ†’ request denied
42
+
43
+ This allows:
44
+
45
+ * Short bursts of traffic
46
+ * Strict control of long-term rate
47
+ * Smooth throttling instead of hard blocks
48
+
49
+ Example:
50
+
51
+ | Setting | Value |
52
+ | ----------- | ----------------- |
53
+ | Capacity | 10 |
54
+ | Refill Rate | 5 tokens / second |
55
+
56
+ User can send 10 requests instantly, then 5 per second after.
57
+
58
+ ---
59
+
60
+ ## Why Redis + Lua?
61
+
62
+ Without Lua:
63
+
64
+ ```
65
+ GET tokens
66
+ CHECK tokens
67
+ SET tokens
68
+ ```
69
+
70
+ This causes race conditions under concurrency.
71
+
72
+ With Lua:
73
+
74
+ ```
75
+ All logic runs atomically inside Redis.
76
+ ```
77
+
78
+ No race. No burst leak. Fully distributed.
79
+
80
+ ---
81
+
82
+ ## Install
11
83
 
12
84
  ```bash
13
85
  npm i redis-lua-rate-limiter
14
86
  ```
15
87
 
16
- ## Usage
88
+ ---
89
+
90
+ ## Basic Usage (IP based)
17
91
 
18
92
  ```ts
19
93
  import express from "express";
20
94
  import { createRateLimiter } from "redis-lua-rate-limiter";
21
95
 
96
+ const app = express();
97
+
22
98
  const limiter = await createRateLimiter({
23
99
  redisUrl: "redis://localhost:6379",
24
100
  default: { capacity: 10, refillRate: 5 },
@@ -26,53 +102,165 @@ const limiter = await createRateLimiter({
26
102
  });
27
103
 
28
104
  app.use(limiter.middleware());
105
+
106
+ app.get("/", (_, res) => res.send("OK"));
107
+
108
+ app.listen(3000);
109
+ ```
110
+
111
+ ---
112
+
113
+ ## ๐Ÿ”‘ API Key Based Rate Limiting
114
+
115
+ ```ts
116
+ const limiter = await createRateLimiter({
117
+ redisUrl: "redis://localhost:6379",
118
+ default: { capacity: 20, refillRate: 10 },
119
+
120
+ keyGenerator: (req) => {
121
+ const apiKey = req.headers["x-api-key"];
122
+ if (typeof apiKey === "string") return `rate:${apiKey}`;
123
+ return `rate:${req.ip}`;
124
+ },
125
+ });
126
+ ```
127
+
128
+ ---
129
+
130
+ ## ๐Ÿ›ฃ๏ธ Per Route Limits
131
+
132
+ ```ts
133
+ const limiter = await createRateLimiter({
134
+ redisUrl: "redis://localhost:6379",
135
+
136
+ default: { capacity: 10, refillRate: 5 },
137
+
138
+ routes: {
139
+ "/login": { capacity: 3, refillRate: 1 },
140
+ "/heavy": { capacity: 2, refillRate: 0.5 },
141
+ },
142
+ });
29
143
  ```
30
144
 
31
- ## Features
145
+ ---
32
146
 
33
- - Token bucket algorithm
34
- - Redis Lua atomic execution
35
- - Per API key / IP limiting
36
- - Per route limits
37
- - Rate limit headers
38
- - Works across multiple Node servers
147
+ ## ๐Ÿ“ก Rate Limit Headers
39
148
 
40
- ## Benchmark
149
+ When `headers: true`:
41
150
 
42
151
  ```
43
- $ npx autocannon -c 1000 -d 15 http://localhost:3000
44
- Running 15s test @ http://localhost:3000
152
+ X-RateLimit-Limit: 10
153
+ X-RateLimit-Remaining: 4
45
154
  ```
46
155
 
47
- Tested with 1000 connections using autocannon
156
+ Similar to real API gateways.
48
157
 
158
+ ---
159
+
160
+ ## Options Reference
161
+
162
+ ```ts
163
+ createRateLimiter({
164
+ redisUrl: string, // required
165
+
166
+ default: {
167
+ capacity: number,
168
+ refillRate: number
169
+ },
170
+
171
+ routes?: Record<string, {
172
+ capacity: number,
173
+ refillRate: number
174
+ }>,
175
+
176
+ keyGenerator?: (req: Request) => string,
177
+
178
+ headers?: boolean
179
+ })
49
180
  ```
50
- โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
51
- โ”‚ Stat โ”‚ 2.5% โ”‚ 50% โ”‚ 97.5% โ”‚ 99% โ”‚ Avg โ”‚ Stdev
52
- โ”‚ Max โ”‚
53
- โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
54
- โ”‚ Latency โ”‚ 203 ms โ”‚ 214 ms โ”‚ 253 ms โ”‚ 481 ms โ”‚ 220.74 ms โ”‚ 41.38 ms โ”‚ 759 ms โ”‚
55
- โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
56
- โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
57
- โ”‚ Stat โ”‚ 1% โ”‚ 2.5% โ”‚ 50% โ”‚ 97.5% โ”‚ Avg โ”‚ Stdev โ”‚ Min โ”‚
58
- โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
59
- โ”‚ Req/Sec โ”‚ 2,739 โ”‚ 2,739 โ”‚ 4,595 โ”‚ 5,003 โ”‚ 4,516.4 โ”‚ 558.22 โ”‚ 2,739 โ”‚
60
- โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
61
- โ”‚ Bytes/Sec โ”‚ 898 kB โ”‚ 898 kB โ”‚ 1.51 MB โ”‚ 1.64 MB โ”‚ 1.48 MB โ”‚ 183 kB โ”‚ 897 kB โ”‚
62
- โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
181
+
182
+ ---
183
+
184
+ ## ๐Ÿงช Benchmark (autocannon)
185
+
186
+ Tested under heavy concurrency:
187
+
188
+ ```bash
189
+ npx autocannon -c 1000 -d 15 http://localhost:3000
63
190
  ```
64
- Req/Bytes counts sampled once per second.
65
- # of samples: 15
191
+
192
+ Result:
193
+
66
194
  ```
67
195
  160 2xx responses, 67579 non 2xx responses
68
- 69k requests in 15.22s, 22.2 MB read
69
-
196
+ 69k requests in 15s
197
+ ~4500 req/sec
70
198
  ```
71
199
 
72
- Shows strict enforcement without race conditions.
200
+ This shows:
201
+
202
+ * Strict enforcement
203
+ * No race condition
204
+ * No burst leak
205
+ * Fully atomic behavior
206
+
207
+ ---
208
+
209
+ ## Docker (for Redis)
210
+
211
+ ```yaml
212
+ version: "3.9"
213
+ services:
214
+ redis:
215
+ image: redis:7
216
+ ports:
217
+ - "6379:6379"
218
+ ```
73
219
 
74
- ## Docker
220
+ Run:
75
221
 
76
222
  ```bash
77
223
  docker compose up
78
224
  ```
225
+
226
+ ---
227
+
228
+ ## Architecture
229
+
230
+ ```
231
+ Client โ†’ Express โ†’ Redis Lua โ†’ Allow / Deny
232
+ ```
233
+
234
+ All Node instances share the same Redis logic.
235
+
236
+ ---
237
+
238
+ ## Features
239
+
240
+ * Token bucket algorithm
241
+ * Redis Lua atomic execution
242
+ * Works across multiple servers
243
+ * Per IP / API key / user limiting
244
+ * Per route limits
245
+ * Rate limit headers
246
+ * TypeScript support
247
+ * Production ready
248
+
249
+ ---
250
+
251
+ ## When should you use this?
252
+
253
+ * Horizontally scaled Node.js apps
254
+ * Microservices
255
+ * API servers
256
+ * Authentication endpoints
257
+ * Public APIs
258
+
259
+ ---
260
+
261
+ ## ๐Ÿ“œ License
262
+
263
+ MIT
264
+
265
+ ---
266
+
package/package.json CHANGED
@@ -1,11 +1,13 @@
1
1
  {
2
2
  "name": "redis-lua-rate-limiter",
3
- "version": "1.0.0",
3
+ "version": "1.0.1",
4
4
  "description": "Distributed token-bucket rate limiter using Redis Lua scripts for Node.js/Express",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
7
- "files": ["dist", "lua"],
8
-
7
+ "files": [
8
+ "dist",
9
+ "lua"
10
+ ],
9
11
  "scripts": {
10
12
  "build": "tsc",
11
13
  "dev": "ts-node-dev example/express-app.ts"
@@ -21,7 +23,6 @@
21
23
  "author": "shubhankar kumar singh",
22
24
  "license": "MIT",
23
25
  "dependencies": {
24
-
25
26
  "ioredis": "^5.9.2"
26
27
  },
27
28
  "peerDependencies": {