DeveloperBreeze

Build a Custom Rate Limiter in Node.js with Redis

Protect your API from abuse and learn how rate limiting works under the hood.

When developing web apps or APIs, it’s critical to prevent users from overwhelming your server. That’s where rate limiting comes in. In this guide, we’ll build a custom rate limiter in Node.js using Redis—no libraries, no magic, just code you control and understand.


What You’ll Learn

  • How to use Redis to count and throttle requests
  • How to implement reusable middleware in Express
  • How to rate limit by IP or API key
  • Why this method is better for learning and customization

Prerequisites

  • Node.js installed
  • Redis running locally (or via Docker)
  • Basic Express.js knowledge

Step 1: Set Up the Project

mkdir node-rate-limiter
cd node-rate-limiter
npm init -y
npm install express redis dotenv

Create a .env file:

REDIS_URL=redis://localhost:6379

Step 2: Connect to Redis

// redisClient.js
const redis = require("redis");

const client = redis.createClient({ url: process.env.REDIS_URL });

client.on("error", (err) => console.error("Redis error:", err));
client.connect();

module.exports = client;

Step 3: Write the Rate Limiting Middleware

// rateLimiter.js
const client = require("./redisClient");

const rateLimiter = (limit = 100, windowSec = 3600) => {
  return async (req, res, next) => {
    const ip = req.ip;
    const key = `rate_limit:${ip}`;

    const current = await client.get(key);

    if (current !== null && parseInt(current) >= limit) {
      return res.status(429).json({ error: "Too many requests. Try later." });
    }

    const multi = client.multi();
    multi.incr(key);
    if (!current) {
      multi.expire(key, windowSec);
    }
    await multi.exec();

    next();
  };
};

module.exports = rateLimiter;

Step 4: Use It in Your Express App

// server.js
require("dotenv").config();
const express = require("express");
const rateLimiter = require("./rateLimiter");

const app = express();
const PORT = 3000;

app.use(rateLimiter(100, 3600)); // 100 requests/hour per IP

app.get("/", (req, res) => {
  res.send("Welcome! You're within rate limit.");
});

app.listen(PORT, () => {
  console.log(`Server running on http://localhost:${PORT}`);
});

Step 5: Test It

Use Postman or curl:

curl http://localhost:3000

After 100 requests within an hour, you’ll get:

{
  "error": "Too many requests. Try later."
}

Bonus: Rate Limit by API Key

Instead of IP address, use API keys for user-specific limits:

const userKey = req.headers['x-api-key'] || req.ip;
const key = `rate_limit:${userKey}`;

You can now:

  • Offer different limits for free vs paid users
  • Log or monitor usage per user

Why This Is Valuable

This isn’t just a quick fix—it’s a deep dive into:

  • Atomic operations with Redis
  • Manual request tracking logic
  • Flexibility to customize based on business rules

You’re no longer blindly relying on a package—you understand and control the system.


What’s Next?

Want to extend this?

  • Implement sliding windows
  • Use Redis tokens (token bucket)
  • Add real-time dashboards or admin controls

If you're building any kind of real API, this knowledge will serve you well.


Have questions or want a follow-up tutorial? Leave a comment or reach out—we’d love to help.

More practical Node.js guides →


Related Posts

More content you might like

Tutorial
javascript

Using Node.js to Run JavaScript

  • Run the downloaded installer and follow the installation prompts.
  • Ensure that npm (Node Package Manager) is installed alongside Node.js (it usually is).

Dec 10, 2024
Read More
Tutorial

Connecting a Node.js Application to an SQLite Database Using sqlite3

  • Check Data Types:
  • Ensure that the data types in your SQL statements match the data being inserted.
  • Verify Placeholder Order:
  • Make sure the order of the values provided to stmt.run() matches the order of the placeholders (?) in the SQL statement.
  • Use Debugging Tools:
  • Utilize tools like DB Browser for SQLite to inspect the database file directly.

In this tutorial, you've learned how to integrate an SQLite database into your Node.js application using the sqlite3 package. By following the steps outlined, you've successfully:

Oct 24, 2024
Read More
Tutorial
bash

How to Update Node.js and npm on Ubuntu

node -v
npm -v

If the version is outdated (e.g., Node.js v12 or earlier), it's time to upgrade.

Oct 03, 2024
Read More
Tutorial
javascript nodejs +1

Building a GraphQL API with Node.js and Apollo Server

GraphQL allows you to pass arguments to fields and use variables in queries for dynamic data fetching.

Modify the schema to include a query for fetching a book by title:

Aug 12, 2024
Read More

Discussion 0

Please sign in to join the discussion.

No comments yet. Be the first to share your thoughts!