Skip to main content

AWS Lambda Rate Limiting with Serverless Redis

In this tutorial, we will throttle AWS Lambda functions using Serverless Redis based on the client's IP address.

See code.

See demo.

1 Serverless Project Setup#

If you do not have it already, install serverless framework via: npm install -g serverless

In any folder run serverless as below:

>> serverless
Serverless: No project detected. Do you want to create a new one? YesServerless: What do you want to make? AWS Node.jsServerless: What do you want to call this project? serverless-rate-limiting
Project successfully created in 'serverless-rate-limiting' folder.
You can monitor, troubleshoot, and test your new service with a free Serverless account.
Serverless: Would you like to enable this? NoYou can run the “serverless” command again if you change your mind later.
note

See Using AWS SAM, if you prefer AWS SAM over Serverless Framework.

Inside the project folder create a node project with the command:

npm init

Then install the redis client and rate limiting libraries with:

npm install ioredis async-ratelimiter request-ip

Update the serverless.yml as below. Copy your Redis URL from console and replace below:

service: serverless-rate-limitingframeworkVersion: '2'provider:  name: aws  runtime: nodejs12.x  lambdaHashingVersion: 20201221functions:  hello:    handler: handler.hello    events:      - httpApi:          path: /hello          method: get
note

For the best performance choose the same region for your Lambda function and Upstash database.

2 Create a Redis (Upstash) Database#

Create a database from Upstash console

3 Code#

Edit handler.js and replace your REDIS_URL below.

const RateLimiter = require('async-ratelimiter')const Redis = require('ioredis')const { getClientIp } = require('request-ip')
const rateLimiter = new RateLimiter({    db: new Redis("YOUR_REDIS_URL"),    max: 1,    duration: 5_000})
module.exports.hello = async (event) => {    const clientIp = getClientIp(event) || 'NA'    const limit = await rateLimiter.get({id: clientIp})    if (!limit.remaining) {        return {            statusCode: 429,            body: JSON.stringify(                {                    message: 'Sorry, you are rate limited. Wait for 5 seconds'                },            ),        };    }
    return {        statusCode: 200,        body: JSON.stringify(            {                message: 'hello!'            },        ),    };};

Above, we have configured the rate limiting to accept 1 request from the same IP address in 5 seconds.

4 Deploy and Try the API#

Deploy your functions with:

serverless deploy

The command will deploy the function and show the endpoint url. Click to the endpoint url. If you refresh your page, you will see that your request is throttled.