Skip to main content

Command Palette

Search for a command to run...

How to Implement Rate Limiting with Redis

How to Easily Use Redis for Rate Limiting Without Additional Dependencies

Published
7 min read
How to Implement Rate Limiting with Redis
K

Welcome to my blog! I’m an AI and Data Science undergrad with a knack for full-stack web development, machine learning, and working with LLMs. Proficient in C++, Java, JavaScript, and TypeScript, I’m into system design, microservices and creating scalable, user-friendly web apps. Follow along for some crazy tips, tricks and hacks for implementing complex services with minimal efforts. Here, I share my tech journey whilst trying to improving myself. My interests outside of code are anime, web novels, food, and swimming. Dive in and let's explore together!

Disclaimer

If you do not have any idea what Redis is, and a total noob in respect to this technology, then give a quick read to the following article, and then you will be good to go, and take your boring CRUD application to next level.

Prerequisites:

  • Redis

  • TypeScript

  • Express js

What is Rate Limiting?

Rate limiting is like a speed limit on a road, but for a web app. Just as a speed limit controls how fast cars can go to prevent accidents, rate limiting controls how many requests a user or a system can make to a web app in a certain period of time.

Imagine you're at a bakery that only lets you buy 5 cookies per hour. If you try to buy more, the cashier will say, "Sorry, you’ve reached your limit. Come back later." Similarly, if a web app has a rate limit of 100 requests per minute, and you try to send 101 requests in that minute, the app will block the extra request and tell you to slow down.

This helps the web app avoid being overwhelmed by too many requests at once, which could slow it down or even make it crash. It also helps prevent misuse, like someone trying to spam or attack the app by sending too many requests.

How it is used in market

Big organizations use a variety of sophisticated methods and tools to implement rate limiting, ensuring that their web applications remain secure, responsive, and available. Here are some well-equipped ways they do this:

1. Token Bucket Algorithm

  • How It Works: Imagine a bucket that holds tokens. Every request a user makes takes a token from the bucket. Tokens are added back at a fixed rate. If the bucket runs out of tokens, further requests are denied until more tokens are added.

  • Why It's Used: This approach is flexible, allowing occasional bursts of activity while maintaining an overall limit on the rate of requests.

2. Leaky Bucket Algorithm

  • How It Works: Picture a bucket with a small hole at the bottom, allowing water (requests) to leak out at a constant rate. When a request comes in, it's added to the bucket. If the bucket is full, new requests are discarded or delayed.

  • Why It's Used: This method smooths out traffic bursts, ensuring that requests are processed at a steady rate.

3. Fixed Window Rate Limiting

  • How It Works: Requests are counted within a fixed time window (e.g., 100 requests per minute). If the limit is reached within that window, further requests are blocked until the window resets.

  • Why It's Used: Simple and straightforward, this method is easy to implement and understand.

4. Sliding Window Rate Limiting

  • How It Works: Similar to the fixed window, but instead of resetting at fixed intervals, the window "slides" with each request, offering more precise control over request rates.

  • Why It's Used: This approach provides better accuracy and fairness in rate limiting, especially in high-traffic environments.

5. Rate Limiting Middleware in API Gateways

  • How It Works: API gateways like Kong, Nginx, or AWS API Gateway come with built-in rate-limiting features. They act as intermediaries between clients and servers, applying rate limits based on predefined rules.

  • Why It's Used: These solutions are scalable, customizable, and can be integrated into a broader API management strategy.

6. Distributed Rate Limiting

  • How It Works: Rate limiting is applied across multiple servers or data centers, ensuring that limits are enforced globally rather than just on a single server. Tools like Redis are often used to manage state across distributed systems.

  • Why It's Used: Ensures consistency and prevents users from bypassing limits by switching servers.

7. IP-Based Rate Limiting

  • How It Works: Requests from the same IP address are limited based on predefined rules (e.g., 10 requests per second per IP).

  • Why It's Used: Useful for protecting against certain types of attacks, such as Distributed Denial of Service (DDoS).

8. User-Based Rate Limiting

  • How It Works: Rate limits are applied based on user accounts rather than IP addresses. This method can be more fair and effective, especially for apps with authenticated users.

  • Why It's Used: It ensures that limits are applied fairly regardless of the user's location or device.

9. Quota-Based Rate Limiting

  • How It Works: Users are given a quota (e.g., 1000 API calls per day), which they can use as they like. Once the quota is exhausted, they must wait until the next day or purchase more.

  • Why It's Used: Common in SaaS platforms where users subscribe to different tiers of service.

10. Dynamic Rate Limiting

  • How It Works: Rate limits are adjusted in real-time based on traffic patterns, system load, or user behavior. For instance, limits might be relaxed during off-peak hours or tightened during a DDoS attack.

  • Why It's Used: Offers flexibility and resilience, adapting to changing conditions automatically.

11. Machine Learning-Based Rate Limiting

  • How It Works: Machine learning algorithms analyze traffic patterns and user behavior to dynamically adjust rate limits. These systems can detect anomalies and predict potential abuse, applying limits proactively.

  • Why It's Used: Provides intelligent, context-aware rate limiting that can adapt to new threats and optimize user experience.

12. Rate Limiting via Content Delivery Networks (CDNs)

  • How It Works: CDNs like Cloudflare or Akamai offer rate limiting as a service, where requests are filtered and limited before they even reach the origin server.

  • Why It's Used: Offloads the rate limiting burden from the application servers, improves performance, and adds an extra layer of security.

These methods are often used in combination, tailored to the specific needs of the organization and the application. By employing such advanced strategies, big organizations can efficiently manage traffic, prevent abuse, and ensure that their web apps remain fast and reliable for all users.

Confused?

Now you might be wondering how to even implement it with the most minimal code?

Let me tell you the easiest way to implement. We will combine 6th and 7th method and perform IP-based Rate limiting by using Redis.

Make sure you have redis already setup in your project, if not then follow my previous articles. If everything is setup then in next 5 minutes you will have rate limiting setup in your project.

The demo is in pure typescript and using express js as backend service.

How we do it. The chad methodology.

We will create a middleware for our rate limiter and set it up on every port where rate limiting is desired.

Creating a middleware:

export const rateLimiter = ({
  limit = 20,
  timer = 60,
  key,
}: rateLimiterProps) =>
  TryCatch(async (req, res, next) => {
    const clientIp = req.headers["x-forwarded-for"] || req.socket.remoteAddress;
    const fullKey = `${clientIp}:${key}:request_count`;
    const requestCount = await redis.incr(fullKey);

    if (requestCount === 1) {
      await redis.expire(fullKey, timer);
    }
    const remainingTime = await redis.ttl(fullKey);

    if (requestCount > limit) {
      return res.status(429).json({
        success: false,
        message: `You have exceeded the ${limit} requests in ${remainingTime} seconds. Please try again later.`,
      });
    }

    next();
  });
  • "rateLimiterProps"

      export type rateLimiterProps = {
        limit: number;
        timer: number;
        key: string;
      };
    
  • "TryCatch"

      export const TryCatch = (fn:ControllerType) => 
          (req: Request, res: Response, next: NextFunction) => 
          Promise.resolve(fn(req, res, next)).catch(next);
    

How to use this middleware

Some of the examples use cases while writing express routes are

app.get(
  "products/latest",
  rateLimiter({ limit: 20, timer: 60, key: "latest-product" }),
  getLatestProducts
);

app.get(
  "orders/all",
  adminOnly,
  rateLimiter({ limit: 20, timer: 60, key: `all-orders` }),
  allOrders
);

Congratulations, within just 10-15 minutes you have implemented rate limiting which is a fairly advance feature to implement in the most easiest way possible without depending on any 3rd party libraries. And now your boring CRUD application stepped up to a boring CRUD application with rate limiting 😎😎😎.

This is a very unique way of doing it, and people watching it will be impressed when they witness it for the first time.

Attention. You won't find this anywhere, so subscribe for more such tricks and hacks regarding software development, it will be my motivation for sharing more.

Conclusion

In conclusion, implementing rate limiting with Redis is a powerful and efficient way to protect your web applications from being overwhelmed by excessive requests. By following the steps outlined in this article, you can easily set up IP-based rate limiting using Redis and Express.js, ensuring that your application remains responsive and secure. This method not only helps in managing traffic but also adds an extra layer of security against potential misuse and attacks. With just a few lines of code, you can elevate your application's performance and reliability, making it ready to handle real-world traffic scenarios. Keep exploring and enhancing your skills, and soon you'll be able to tackle even more advanced features with confidence. Happy coding!