Redis as custom storage for NestJS rate limiter
A rate limiter is a standard protection technique against brute force and DDoS attacks. NestJS provides a module for it, and the default storage is in-memory. Custom storage, Redis in this case, should be injected inside ThrottlerModule
configuration.
Configuration
The configuration should contain
TTL (time to live) in seconds
maximum number of requests within TTL
Redis URL
// app.module.ts
import { APP_GUARD } from '@nestjs/core';
import { ThrottlerGuard, ThrottlerModule } from '@nestjs/throttler';
import { ThrottlerStorageRedisService } from 'nestjs-throttler-storage-redis';
// ...
@Module({
imports: [
ThrottlerModule.forRootAsync({
inject: [CustomConfigService],
useFactory: (configService: CustomConfigService) => ({
ttl: configService.THROTTLER_TTL_SECONDS,
limit: configService.THROTTLER_LIMIT,
storage: new ThrottlerStorageRedisService(configService.REDIS_URL),
}),
}),
// ...
],
})
export class AppModule {}
API endpoints setup
Binding the throttler guard can be done in multiple ways.
- the guard is bound globally for every API endpoint.
// app.module
import { ThrottlerGuard } from '@nestjs/throttler';
// ...
@Module({
// ...
providers: [{
provide: APP_GUARD,
useClass: ThrottlerGuard,
}],
})
export class AppModule {}
- the global guard is overridden for the specific API endpoint with the
Throttle
decorator.
import { Throttle } from '@nestjs/throttler';
// ...
@Controller('users')
export class UsersController {
@Throttle(USERS_THROTTLER_LIMIT, USERS_THROTTLER_TTL_SECONDS)
@Get()
async getUsers() {}
}
- the global guard is skipped for the specific API endpoint with the
SkipThrottle
decorator.
import { SkipThrottle } from '@nestjs/throttler';
// ...
@Controller('posts')
export class PostsController {
@SkipThrottle()
@Get()
async getPosts() {}
}
Boilerplate
Here is the link to the boilerplate I use for the development.