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.tsimport { 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.
- guard is bound globally for every API endpoint.
// app.moduleimport { ThrottlerGuard } from '@nestjs/throttler';// ...@Module({// ...providers: [{provide: APP_GUARD,useClass: ThrottlerGuard,}],})export class AppModule {}
- 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() {}}
- 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 template I use for the development.