Rate Limit APIs in Node.js with Redis

Rate Limit APIs in Node.js with Redis

ยท

4 min read

Many times, it is required to limit an API call to put some restriction on consumption of a particular resource.

A nice example would be rate limiting sending emails or sending OTP.

Let's say some malicious user ๐Ÿฑโ€๐Ÿ’ป is running a cURL script to generate huge number of OTP in short time span.

Definitely, this case should be handled properly, otherwise we will end up paying a lot of money to the OTP service provider. ๐Ÿค‘

So, in this article I will walk you through how we can have this kind of restriction on some API.

I will use /otp/send as an example and rate limit on phone number but It can be IP of the client as well.

So let's say we have some API,

POST otp/send
{
   "phone": "+918778XXXX78"
}

and we want to restrict it so that a user can only call it 5 times in 10 second of time window.

If you are familiar with express, the API would look like something below,

router.post('/otp/send', sendOTP);

So, it would be nice If we could create a middleware that contains all the logic to decide whether the request to send OTP should proceed or should drop.

Let's create that middleware,

const redis = require('async-redis');
const client = redis.createClient();

module.exports = async (req, res, next) => {
  const { phone } = req.body;  // could be ip as well, ip = req.ip;
  const keyName = phone;
  const current = await client.get(phone);
  if (current && current > 5) {
    throw new Error('Too many requests, please try after sometime!');
  } else {
    await client.multi()
      .incr(keyName)
      .expire(keyName, 10) // number of seconds
      .exec();
    next();
  }
};

Finally, to use above middleware we simply need to attach this to the route,

router.post('/otp/send', rateLimitSendOTP, sendOTP);

This is what happening here,

  • Whenever a user makes first time API call, a key will be set in Redis with expiration of 10 seconds and with counter value 1
  • On next call, if the key isn't expired it will increment the counter by 1
  • If key exist and the value of the counter is greater than 5 it will throw and error
  • After 10 second key will be deleted and the cycle will start again

There are other rate limiter patterns in Redis, I have used pattern 1 here, I highly recommended to go through the doc at least for once.

Links:

Redis Pattern: Rate limiter 1

Async Redis For Node

Happy Learning! ๐Ÿ˜Š

Did you find this article valuable?

Support Sujeet Agrahari by becoming a sponsor. Any amount is appreciated!