Menu
Medium #system-design·April 1, 2026

Implementing Distributed Rate Limiting with Redis and PM2 for Node.js APIs

This article details how to implement a robust rate-limiting and API blocking mechanism for Node.js applications in a production environment. It focuses on using Redis as a distributed store for rate-limiting counters and PM2 for managing multiple application instances, addressing challenges like concurrency and scalability inherent in distributed systems.

Read original on Medium #system-design

The Need for API Rate Limiting

API rate limiting is a critical component of any public-facing API to prevent abuse, ensure fair resource allocation, and protect backend services from overload. Without it, a single malicious user or misconfigured client can degrade performance for all users or incur significant infrastructure costs. The core challenge in a distributed system is maintaining a consistent view of request counts across multiple application instances.

Architecture for Distributed Rate Limiting

The proposed architecture leverages Redis as a centralized, high-performance data store for tracking API request counts. Each Node.js application instance, managed by PM2, would interact with this shared Redis instance to increment counters and check limits. This design ensures that rate limits are enforced consistently across all application instances, even when scaled horizontally.

  • Client: Makes API requests.
  • Load Balancer (e.g., NGINX): Distributes requests to Node.js instances.
  • Node.js Application (managed by PM2): Implements the rate-limiting logic.
  • Redis: Stores rate limit counters and timestamps.

Rate Limiting Logic with Redis

The implementation uses Redis's `INCR` command and `EXPIRE` for managing a sliding window or fixed window counter. For each incoming request, the application would: retrieve the current count for the user/IP from Redis, increment it, and if it exceeds the threshold, block the request. The `EXPIRE` command is crucial for automatically resetting the counter after a defined time window. This approach supports various rate-limiting algorithms, with the sliding window being most effective for smoothing out bursts.

javascript
const redisClient = require('./redis-client');

async function checkRateLimit(key, limit, windowSeconds) {
    const current = await redisClient.incr(key);
    if (current === 1) {
        await redisClient.expire(key, windowSeconds);
    }
    return current <= limit;
}
💡

PM2 for Process Management

PM2 (Process Manager 2) is used to keep Node.js applications alive forever, reload them without downtime, and facilitate common system admin tasks. In a rate-limiting context, PM2 ensures that multiple instances of the rate-limiting middleware are running, distributing the load and providing high availability for the API service itself, while Redis handles the distributed state.

rate limitingredisnode.jsapi securitymicroservicesdistributed systemspm2concurrency

Comments

Loading comments...