nest-ratelimit-pro
v1.0.0
Published
Advanced rate limiting and throttling middleware for NestJS with support for multiple algorithms, distributed systems, and flexible storage backends
Downloads
188
Maintainers
Readme
nest-ratelimit-pro
Advanced rate limiting and throttling middleware for NestJS with support for multiple algorithms, distributed systems, and flexible storage backends.
🚀 Features
Multiple Rate Limiting Algorithms
- Fixed Window Counter
- Sliding Window Log
- Token Bucket
- Sliding Window Counter
Flexible Key Strategies
- IP-based rate limiting
- User ID-based (requires authentication)
- API Key-based
- Custom key extraction
Storage Backends
- In-memory storage (single instance)
- Redis support (distributed)
- Custom storage adapters
Advanced Features
- Cost-based rate limiting
- Per-route configuration
- Skip conditions
- Automatic cleanup
- Response headers
- Custom error messages
Production-Ready
- TypeScript with strict typing
- Comprehensive test coverage
- Docker support
- Monitoring & metrics ready
📦 Installation
npm install nest-ratelimit-proOptional dependencies:
# For Redis storage
npm install ioredis🔧 Quick Start
1. Basic Setup
import { Module } from '@nestjs/common';
import { RateLimitModule } from 'nest-ratelimit-pro';
@Module({
imports: [
RateLimitModule.forRoot({
limit: 100, // 100 requests
duration: '1m', // per 1 minute
keyStrategy: 'ip', // Rate limit by IP address
}),
],
})
export class AppModule {}2. Apply Guard to Controllers
import { Controller, Get, UseGuards } from '@nestjs/common';
import { RateLimitGuard } from 'nest-ratelimit-pro';
@Controller('api')
@UseGuards(RateLimitGuard)
export class ApiController {
@Get('data')
async getData() {
return { message: 'Success!' };
}
}3. Per-Route Configuration
import { RateLimit } from 'nest-ratelimit-pro';
@Controller('api')
export class ApiController {
// Override global limit for this route
@RateLimit({ limit: 5, duration: '1m' })
@Get('expensive')
async expensiveOperation() {
return { data: 'Heavy computation' };
}
// Skip rate limiting for this route
@SkipRateLimit()
@Get('health')
async healthCheck() {
return { status: 'ok' };
}
}📖 Configuration Options
Module Options
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| limit | number | Required | Maximum requests allowed |
| duration | string | Required | Time window (e.g., '1m', '1h') |
| algorithm | RateLimitAlgorithm | FIXED_WINDOW | Algorithm to use |
| keyStrategy | RateLimitKeyStrategy | IP | How to identify requesters |
| keyExtractor | Function | - | Custom key extraction |
| storage | Type<RateLimitStorage> | MemoryStorage | Storage backend |
| keyPrefix | string | 'ratelimit:' | Prefix for storage keys |
| apiKeyHeader | string | 'X-API-Key' | API key header name |
| enableCostBased | boolean | false | Enable cost-based limiting |
| blockDuration | number | 0 | Block duration in seconds |
| skipPaths | string[] | [] | Paths to skip |
| enabled | boolean | true | Enable/disable globally |
| errorMessage | string | - | Custom error message |
| includeHeaders | boolean | true | Include rate limit headers |
🎯 Rate Limiting Algorithms
Fixed Window
Simple counter that resets at fixed intervals:
RateLimitModule.forRoot({
algorithm: RateLimitAlgorithm.FIXED_WINDOW,
limit: 100,
duration: '1m',
});Pros: Simple, low memory Cons: Burst at window edges
Sliding Window
More accurate, prevents burst:
RateLimitModule.forRoot({
algorithm: RateLimitAlgorithm.SLIDING_WINDOW,
limit: 100,
duration: '1m',
});Pros: Smooth rate limiting Cons: Higher memory usage
Token Bucket
Allows bursts with token refill:
RateLimitModule.forRoot({
algorithm: RateLimitAlgorithm.TOKEN_BUCKET,
limit: 100,
duration: '1m',
});Pros: Flexible, allows controlled bursts Cons: More complex
🔑 Key Strategies
IP-Based
RateLimitModule.forRoot({
keyStrategy: RateLimitKeyStrategy.IP,
limit: 100,
duration: '1m',
});User ID-Based
RateLimitModule.forRoot({
keyStrategy: RateLimitKeyStrategy.USER_ID,
limit: 1000,
duration: '1h',
});Requires authentication middleware that sets request.user.id.
API Key-Based
RateLimitModule.forRoot({
keyStrategy: RateLimitKeyStrategy.API_KEY,
apiKeyHeader: 'X-API-Key',
limit: 10000,
duration: '1d',
});Custom Key Extractor
RateLimitModule.forRoot({
keyStrategy: RateLimitKeyStrategy.CUSTOM,
keyExtractor: (request) => {
return `${request.user?.id}-${request.headers['x-tenant-id']}`;
},
limit: 100,
duration: '1m',
});💰 Cost-Based Rate Limiting
Assign different costs to different operations:
@Controller('api')
export class ApiController {
@RateLimit({ cost: 1 })
@Get('light')
async lightOperation() {
return { data: 'Quick response' };
}
@RateLimit({ cost: 10 })
@Post('heavy')
async heavyOperation() {
return { data: 'Expensive computation' };
}
}With a limit of 100, you can make:
- 100 light operations, or
- 10 heavy operations, or
- Any combination totaling 100 cost
🗄️ Storage Backends
Memory Storage (Default)
import { MemoryRateLimitStorage } from 'nest-ratelimit-pro';
RateLimitModule.forRoot({
storage: MemoryRateLimitStorage,
limit: 100,
duration: '1m',
});Use for: Single-instance applications
Redis Storage
import { RedisRateLimitStorage } from 'nest-ratelimit-pro';
RateLimitModule.forRoot({
storage: RedisRateLimitStorage,
redisUrl: 'redis://localhost:6379',
limit: 100,
duration: '1m',
});Use for: Distributed applications, multiple instances
📊 Response Headers
When rate limiting is active, these headers are included:
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 45
X-RateLimit-Reset: 1234567890
Retry-After: 30 (when limit exceeded)🛡️ Skip Conditions
Skip Specific Paths
RateLimitModule.forRoot({
skipPaths: ['/health', '/metrics', '/public/*'],
limit: 100,
duration: '1m',
});Skip with Custom Logic
RateLimitModule.forRoot({
skipIf: (request) => {
return request.headers['x-internal-request'] === 'true';
},
limit: 100,
duration: '1m',
});🧪 Testing
npm test # Run tests
npm run test:cov # With coverage
npm run test:watch # Watch mode📝 Example Application
See the examples directory for complete implementations:
- Basic rate limiting
- Cost-based limiting
- Redis integration
- Custom storage adapter
🤝 Contributing
Contributions are welcome! Please read CONTRIBUTING.md.
📄 License
MIT License - see LICENSE file for details.
👤 Author
Alireza Aminzadeh
- Email: [email protected]
- GitHub: @syeedalireza
- NPM: @syeedalireza
⭐ Support
If this package helped you, please give it a ⭐ on GitHub!
Built with ❤️ for the NestJS community
