Multi-algorithm rate limiting middleware for Express and Fastify, using a Redis-backed store.
npm i rate-limiter-flex ioredisimport express from 'express';
import Redis from 'ioredis';
import { createExpressRateLimiter, RedisStore, byIp } from 'rate-limiter-flex';
const app = express();
const redis = new Redis(process.env.REDIS_URL ?? 'redis://127.0.0.1:6379');
const store = new RedisStore(redis, { keyPrefix: 'myapp' });
app.use(
createExpressRateLimiter({
algorithm: 'fixed-window',
store, // required
limit: 100,
windowMs: 60_000,
keyGenerator: byIp(),
}),
);
app.get('/health', (_req, res) => res.json({ ok: true }));
app.listen(3000);import Fastify from 'fastify';
import Redis from 'ioredis';
import { createFastifyRateLimiter, RedisStore, byIp } from 'rate-limiter-flex';
const app = Fastify();
const redis = new Redis(process.env.REDIS_URL ?? 'redis://127.0.0.1:6379');
const store = new RedisStore(redis, { keyPrefix: 'myapp' });
app.addHook(
'preHandler',
createFastifyRateLimiter({
algorithm: 'sliding-window-log',
store, // required
limit: 20,
windowMs: 10_000,
keyGenerator: byIp(),
}),
);
app.get('/health', async () => ({ ok: true }));
await app.listen({ port: 3000 });fixed-windowsliding-window-logsliding-window-countertoken-bucket(useslimitas bucket capacity; optionalrefillRatetokens/sec)
byIp()byUserId(field = 'user.id')byApiKey(header = 'x-api-key')byRoute()combined(...generators)
On every request:
X-RateLimit-LimitX-RateLimit-RemainingX-RateLimit-Reset
On 429 responses:
Retry-After
You must provide store in RateLimiterOptions.
This package exports RedisStore, which needs a client that matches the RedisClientLike interface (the ioredis client works out of the box).
Note: A
MemoryStoreexists in the repository for internal unit tests, but it is not exported and is not part of the published package API.
See example/server.ts.