DEV Community

Cover image for Mastering Rate Limiting in NestJS with RedisX
Suren Krmoian
Suren Krmoian

Posted on

Mastering Rate Limiting in NestJS with RedisX

Let's talk about something every API developer faces sooner or later: securing your endpoints without sacrificing performance. Rate limiting is a go-to strategy here. It's all about controlling the traffic load by limiting the number of requests a user can make in a set timeframe. If you're using NestJS, RedisX offers a nifty plugin to handle this with several strategies.

Rate Limiting Strategies Explained

Why so many strategies? Well, different scenarios call for different approaches.

  1. Fixed Window: Think of it as the simplest approach. You reset the request count every fixed period, say a minute. Every new minute, users get a fresh quota. It's simple but not great with bursts of traffic.

  2. Sliding Window: A bit more sophisticated. It considers requests over the last window duration, giving a smoother experience. This one's solid for most cases.

  3. Token Bucket: If you're okay with some bursts, go for this. It lets tokens accumulate, and a request consumes a token. No tokens? No request. Simple.

Getting Started with NestJS RedisX

Alright, let's get this into your NestJS app. First things first, install the packages:

npm install @nestjs-redisx/core @nestjs-redisx/rate-limit
Enter fullscreen mode Exit fullscreen mode

Then, configure your module. Use RateLimitPlugin.registerAsync for flexibility, especially if you're into dynamic configs:

import { Module } from '@nestjs/common';
import { ConfigModule, ConfigService } from '@nestjs/config';
import { RedisModule } from '@nestjs-redisx/core';
import { RateLimitPlugin, RateLimitGuard } from '@nestjs-redisx/rate-limit';
import { APP_GUARD } from '@nestjs/core';

@Module({
  imports: [
    ConfigModule.forRoot({ isGlobal: true }),
    RedisModule.forRootAsync({
      imports: [ConfigModule],
      inject: [ConfigService],
      plugins: [
        RateLimitPlugin.registerAsync({
          imports: [ConfigModule],
          inject: [ConfigService],
          useFactory: (config: ConfigService) => ({
            defaultAlgorithm: config.get('RATE_LIMIT_ALGORITHM', 'sliding-window'),
            defaultPoints: config.get('RATE_LIMIT_POINTS', 100),
            defaultDuration: config.get('RATE_LIMIT_DURATION', 60),
          }),
        }),
      ],
      useFactory: (config: ConfigService) => ({
        clients: {
          type: 'single',
          host: config.get('REDIS_HOST', 'localhost'),
          port: config.get('REDIS_PORT', 6379),
        },
      }),
    }),
  ],
  providers: [
    { provide: APP_GUARD, useClass: RateLimitGuard },
  ],
})
export class AppModule {}
Enter fullscreen mode Exit fullscreen mode

Limiting Specific Endpoints

Once set up, you can apply rate limits to your routes using the @RateLimit decorator. Great for public APIs:

import { Controller, Get } from '@nestjs/common';
import { RateLimit } from '@nestjs-redisx/rate-limit';

@Controller('api')
export class ApiController {
  @Get('data')
  @RateLimit({ points: 10, duration: 60 })
  getData() {
    return { data: 'rate limited endpoint' };
  }

  @Get('search')
  @RateLimit({ points: 5, duration: 60, key: 'ip' })
  search() {
    return { results: [] };
  }
}
Enter fullscreen mode Exit fullscreen mode

Wrapping Up

Incorporating rate limiting can be a game-changer for your API's security and performance. With NestJS RedisX, you've got a powerful toolkit to do just that. Whether you're managing a bustling app or just want to keep things fair, RedisX has got your back. Dive deeper into the docs at nestjs-redisx.dev for more insights.

Top comments (0)