nestjs-redis-rate-limiter
v0.0.2
Published
A production-grade, distributed Token Bucket rate limiter for NestJS using Redis (via ioredis) with fail-fast, fail-open logic and standard HTTP headers.
Readme
NestJS Redis Rate Limiter
A high-performance, production-grade, distributed rate-limiting solution for NestJS applications using Redis (via ioredis) and the Token Bucket algorithm.
Features
- ⚡ Atomic Lua Operations: Prevents race conditions across multiple distributed application nodes using a single, atomic Redis Lua script.
- 🛡️ Fail-Open Resiliency: Ensures your API stays up even if Redis goes offline. Connection issues or command timeouts log warnings but bypass rate limits.
- 🚀 High-Performance Options: Automatically disables the Redis offline queue (
enableOfflineQueue: false) and applies strict command/connection timeouts to fail fast and prevent client request hanging. - 🧠 Smart Caching: Pre-computes the Lua script SHA1 hash and uses
EVALSHAfor execution to minimize bandwidth usage. - 🏷️ Standard Compliance: Returns standard rate-limit response headers (
X-RateLimit-Limit,X-RateLimit-Remaining,X-RateLimit-Reset, andRetry-After). - 👤 Flexible Context Extraction: Automatically identifies users by their Passport/JWT Auth User ID or falls back to their IP address.
Installation
Install the package along with its peer dependency ioredis:
npm install nestjs-redis-rate-limiter ioredisQuick Start
1. Register Modules
Import the RedisModule and RateLimitModule in your root AppModule:
import { Module } from '@nestjs/common';
import { RedisModule } from 'nestjs-redis-rate-limiter';
import { RateLimitModule } from 'nestjs-redis-rate-limiter';
@Module({
imports: [
// Registers the Redis client globally
RedisModule,
RateLimitModule,
],
})
export class AppModule {}Configuring Redis Credentials
By default, the RedisModule connects to localhost:6379. You can configure the credentials using environment variables:
REDIS_HOST(default:'localhost')REDIS_PORT(default:6379)REDIS_PASSWORD(default:undefined)
2. Apply the Rate Limit Guard
Apply the RateLimitGuard and the @RateLimit(limit, window) decorator to your endpoints:
import { Controller, Get, UseGuards } from '@nestjs/common';
import { RateLimit, RateLimitGuard } from 'nestjs-redis-rate-limiter';
@Controller('users')
export class UserController {
@Get('profile')
@UseGuards(RateLimitGuard)
@RateLimit(10, 60) // Allow maximum 10 requests every 60 seconds
getProfile() {
return { message: 'This profile endpoint is rate-limited.' };
}
}Architecture & How It Works
The Token Bucket Algorithm
The limiter is based on the Token Bucket algorithm:
- Each bucket starts with a capacity of
limittokens. - Tokens refill continuously over time at a rate of
limit / windowtokens per second. - Each incoming request consumes exactly
1token. - If there are fewer than
1tokens available, the request is blocked.
Standard Response Headers
When rate limiting is active on a route, every successful response returns the following headers:
X-RateLimit-Limit: Maximum capacity of the token bucket.X-RateLimit-Remaining: Remaining integer tokens.X-RateLimit-Reset: Unix timestamp when the bucket will be completely full.
If a client exceeds their rate limit, they receive an HTTP status code 429 Too Many Requests along with:
Retry-After: Exact ceiling seconds the client must wait before at least 1 token is regenerated.
Example 429 error payload:
{
"statusCode": 429,
"error": "Too Many Requests",
"message": "API rate limit exceeded. Please try again in 4 seconds."
}License
This project is licensed under the MIT License.
