DEV Community

kamran
kamran

Posted on

Rate Limiter: The Unsung Guardian of Your Backend APIs

Modern applications live and die by their APIs. Whether it’s a mobile app, a SaaS dashboard, or a public API consumed by thousands of clients, uncontrolled traffic is dangerous. This is where a Rate Limiter becomes one of the most important yet underrated backend components.

Guard depicting Rate Limiter

In this article, we’ll break down:

  1. What a rate limiter is
  2. Why it is critical
  3. Common rate-limiting strategies
  4. A production-ready Node.js rate limiter with configurable parameters
  5. What Is a Rate Limiter?
  6. A rate limiter is a mechanism that restricts how many requests a client can make to a server within a given time window.

In simple words:

“Ek rule bana do ke ek user / IP / token ek fixed time me kitni requests kar sakta hai.”

Example:

  • Max 100 requests per minute per user
  • Max 5 login attempts per minute
  • Max 10 OTP requests per hour
  • Why Do You Need a Rate Limiter?

Without a rate limiter, your system is vulnerable to:

  1. Brute-Force Attacks: Attackers can try thousands of password combinations in seconds.

  2. DDoS or Traffic Flooding: Even non-malicious traffic (badly written clients) can overload your server.

  3. Resource Exhaustion: Each request consumes:

    • CPU
    • Memory
    • Database connections
    • Network
    • bandwidth
  4. Fair Usage Enforcement: One aggressive client should not degrade experience for everyone else.

Common Rate Limiting Strategies

  1. Fixed Window: Count requests in a fixed time window.
    Example: 0–60 seconds → max 100 requests
    Problem: sudden spikes at window reset.

  2. Sliding Window: Requests are counted in a rolling time window. More accurate but slightly complex.

  3. Token Bucket (Most Popular)
    Bucket has tokens
    Each request consumes a token
    Tokens refill over time
    Used by: AWS, NGINX, API gateways

  4. Leaky Bucket: Requests flow out at a fixed rate, excess is dropped.

Where Should You Apply Rate Limiting?

  • API Gateway (best place)
  • Reverse Proxy (NGINX, Cloudflare)
  • Application Layer (Node.js / Express)
  • Database layer (rare but possible)
  • For most Node.js apps, application-level rate limiting is a solid start.

Node.js Rate Limiter (Configurable & Clean)
Below is a custom Express.js rate limiter middleware using in-memory storage (good for MVPs and small apps).

Features

  • Configurable window size
  • Configurable request limit
  • Per-IP or per-key limiting
  • Clean response with retry info

// rateLimiter.js
const rateLimiter = ({
    windowMs = 60 * 1000, // 1 minute
    maxRequests = 100,
    keyGenerator = (req) => req.ip,
} = {}) => {
    const store = new Map();

    return (req, res, next) => {
        const key = keyGenerator(req);
        const currentTime = Date.now();

        if (!store.has(key)) {
            store.set(key, {
                count: 1,
                startTime: currentTime,
            });
            return next();
        }

        const data = store.get(key);
        const elapsedTime = currentTime - data.startTime;

        if (elapsedTime > windowMs) {
            // Reset window
            store.set(key, {
                count: 1,
                startTime: currentTime,
            });
            return next();
        }

        if (data.count >= maxRequests) {
            const retryAfter = Math.ceil(
                (windowMs - elapsedTime) / 1000
            );

            return res.status(429).json({
                success: false,
                message: "Too many requests",
                retryAfterSeconds: retryAfter,
            });
        }

        data.count += 1;
        store.set(key, data);
        next();
    };
};

module.exports = rateLimiter;
Enter fullscreen mode Exit fullscreen mode

Use in Express JS App


//Using in Express app

const express = require("express");
const rateLimiter = require("./rateLimiter");

const app = express();

// Example: Public API
app.use(
    "/api",
    rateLimiter({
        windowMs: 60 * 1000,
        maxRequests: 100,
    })
);

// Example: Login API (strict)
app.post(
    "/login",
    rateLimiter({
        windowMs: 60 * 1000,
        maxRequests: 5,
        keyGenerator: (req) => req.body.email || req.ip,
    }),
    (req, res) => {
        res.json({ message: "Login attempt processed" });
    }
);

app.listen(3000, () => {
    console.log("Server running on port 3000");
}); 
Enter fullscreen mode Exit fullscreen mode

A rate limiter is not just a performance optimization, it’s a security boundary. If authentication is the lock on your door, rate limiting is the guard standing outside. If you’re building APIs in Node.js, adding a rate limiter early will save you from

Outages

  • Abuse
  • Angry users
  • Expensive scaling problems

Want More Content Like This?

If you found this helpful and want practical developer insights, performance tips, and real-world coding content, make sure to check out my:

Instagram for short, actionable tech reels
YouTube channel for in-depth coding and system design videos
More valuable content is coming soon, see you there.

Top comments (0)