Skip to content

Example of a simple web application with a API rate limiter based on the sliding window strategy, using a Redis cache instead of the Nest.js default throttle guard.

Notifications You must be signed in to change notification settings

deepbludev/rate-limiter-nestjs-redis

Repository files navigation

Description

This repository is an example of a simple web application with a API rate limiter based on the sliding window strategy, using a Redis cache instead of the Nest.js default throttle guard.

It uses a middleware to intercept the request and check if the user has exceeded the limit of requests. To determine this, the middleware keeps a log of the requests made by the user in the last 60 minutes.

If the limit has been exceeded, it returns a 429 TOO MANY REQUESTS status code with an error message with the seconds left until the limiting is lifted. If not, the request is allowed to continue and it is logged.

When the TTL of a logged request is reached, it is cleared from the log. This way, we ensure that the rate limiter works with a concurrency-safe sliding window.

There are 2 sets of routes:

  • Public routes: GET /public/a, /public/b, /public/c. These routes do not require authentication and measure rate limit per ip address.

  • Private routes: GET /private/a, /private/b, /private/c. These routes require authentication via API Key in request header and measure rate limit per API Key. The API Key should be passed in the x-api-key header.

The limits for both public and private routes are defined in the .env file, and are set to 100 and 200 requests per hour by default, respectively.

The rate limiter also considers the weight of each request to calculate the rate limit. For example, if the limit is 100 requests per hour, and the weight of the request is 2, then the user can make 50 requests per hour.

Each route has a different predefined request weight to calculate the rate limit. These weights are defined in the public.routes.ts and private.routes.ts files.

The weight of the logged requests is also stored in the Redis cache, so that the rate limiter can calculate the rate limit based on the weight of the requests made by the user.

Requests are logged in a Redis cache with a key with the following format: rate-limit:{token}:{uuid}, where token is the API token or the IP address and uuid is an autogenerated UUID. The value of the key is the weight of the request.

Installation

After cloning, install the dependencies:

# install dependencies
$ npm install

The app uses a Redis cache to store the rate limit data. There is a docker-compose file that starts a Redis container. To start the Redis container, run the following command:

# start redis container
$ docker-compose up -d

There is a simple e2e test that checks if the rate limit is working. For illustration purposes, the rate limiter result will be console logged on every request.

To run the test, run the following command:

# running e2e tests
$ npm run test:e2e

To test the app manually, run the following command:

# running the app
$ npm run start

The app uses a mocked database to check if the API token is among the registered ones.

Any of the following tokens is valid in the mocked database. You can use them to run the app and manually test the rate limiter by sending requests to the public and private routes with one of these keys in the x-api-key header.

  '026a2f78-d68c-4e9e-8c9c-ad53f1c74cec'
  '3dc36e31-0ef7-4fde-9894-1b93ce59e6a3'
  '030743e0-bd92-4baa-801a-282710b5648b'
  '95a80b45-87ab-457f-84e1-e4805e020b1c'
  '974a0506-0d03-40b4-b030-08e30b99130f'

Keep in mind that the rate limit is set to a default of 100 requests per hour for public routes and 200 requests per hour for private routes. This can make manual testing cumbersome unless you change these parameters in the .env file to lower values, such as 5 or 10.

About

Example of a simple web application with a API rate limiter based on the sliding window strategy, using a Redis cache instead of the Nest.js default throttle guard.

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published