API Rate Limiting: Strategies, Algorithms & Production Implementation
Learn how to protect your backend APIs from brute-force attacks and abuse using Token Bucket, Sliding Window, and Redis-backed rate limiters.

Why Rate Limiting Is Essential#
Every public web API is vulnerable to brute-force credential stuffing, web scraping, and denial-of-service (DoS) traffic. Without rate limiting, a single rogue script can overwhelm your database and bring down your application.
API Rate Limiting restricts the number of requests a client (identified by IP address or API key) can make within a given time window.
1. Rate Limiting Algorithms Explained#
A. Fixed Window Counter - Divides time into fixed intervals (e.g., 1-minute windows: 12:00–12:01). - **Flaw:** Traffic spikes at boundary edges (100 requests at 12:00:59 and 100 requests at 12:01:01 can overload the server).
B. Sliding Window Log / Counter (Industry Standard) - Calculates a moving window relative to the current timestamp. - **Advantage:** Prevents boundary bursts and provides smooth rate enforcement.
2. Implementing Redis-Backed Rate Limiting in Node.js#
const express = require("express");
const rateLimit = require("express-rate-limit");
const RedisStore = require("rate-limit-redis");
const { redisClient } = require("./redis");
const app = express();
// Create a distributed rate limiter backed by Redis
const apiLimiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15 minutes
max: 100, // Limit each IP to 100 requests per 15 minutes
standardHeaders: true, // Return standard RateLimit-* headers
legacyHeaders: false,
message: {
success: false,
error: "Too many requests. Please try again in 15 minutes.",
},
});
// Apply rate limiter to sensitive authentication routes
app.use("/api/v1/auth/login", apiLimiter);3. Standard HTTP Response Headers#
RateLimit-Limit: Total allowed requests in the current window.RateLimit-Remaining: Remaining requests available before hitting the limit.RateLimit-Reset: Unix timestamp when the quota resets.HTTP 429 Too Many Requests: Sent when the limit is exceeded.
5. Implementing Client-Side Exponential Backoff#
When an API client receives an HTTP 429 Too Many Requests response, it should never immediately retry in a tight loop. Instead, use Exponential Backoff with Jitter:
async function fetchWithRetry(url: string, retries = 3, delay = 1000): Promise<Response> {
try {
const response = await fetch(url);
if (response.status === 429 && retries > 0) {
// Add random jitter to prevent thundering herd problem
const jitter = Math.random() * 200;
const waitTime = delay + jitter;
console.warn(`Rate limited. Retrying in ${Math.round(waitTime)}ms...`);
await new Promise((resolve) => setTimeout(resolve, waitTime));
return fetchWithRetry(url, retries - 1, delay * 2);
}
return response;
} catch (error) {
if (retries > 0) {
await new Promise((resolve) => setTimeout(resolve, delay));
return fetchWithRetry(url, retries - 1, delay * 2);
}
throw error;
}
}6. Tiered Rate Limiting by User Role#
In production SaaS APIs, different tiers of users require different rate quotas. Implement tiered rate limiting by extracting user subscription claims from JWT tokens:
import { Request } from "express";
import rateLimit from "express-rate-limit";
export const dynamicTierRateLimiter = rateLimit({
windowMs: 60 * 1000, // 1 minute window
max: (req: Request) => {
const userRole = (req as any).user?.tier;
if (userRole === "enterprise") return 1000; // 1,000 req/min
if (userRole === "pro") return 300; // 300 req/min
return 60; // 60 req/min for free tier
},
keyGenerator: (req: Request) => {
return (req as any).user?.id || req.ip || "anonymous";
},
message: {
success: false,
error: "API rate limit exceeded for your current plan tier.",
},
});7. Frequently Asked Questions (FAQ)#
Q: How do I handle rate limiting for users behind a shared corporate proxy or NAT? If thousands of corporate employees share a single public IP address, pure IP-based rate limiting can mistakenly lock out legitimate users. To solve this, use a compound rate limit key: `${clientIp}:${userId || sessionId}` for authenticated endpoints.
Q: What is the difference between Rate Limiting and Web Application Firewall (WAF) filtering? A WAF (such as Cloudflare or AWS WAF) inspects HTTP request payloads at the edge to block malicious SQL injections, XSS payloads, and recognized bot networks before they touch your server. Application rate limiters enforce fine-grained business logic rules (such as 10 PDF exports per hour per paid account).

Published by
Vyuhantrix Team
Web & Systems Engineering · Vyuhantrix
Vyuhantrix is an open technology learning platform based in Ahmedabad, India, publishing step-by-step programming tutorials, system design breakdowns, and free developer tools.
Keep Learning
Recommended Guides
The Definitive Full-Stack Web Development Roadmap (2026 Edition)
A complete step-by-step masterclass covering modern HTML5/CSS, TypeScript, Next.js App Router, Server Components, API Design, and Cloud Edge Deployments.
System Design Fundamentals: Building Scalable & Resilient Distributed Systems
Learn how to architect high-availability applications, manage load balancing, configure caching layers, and implement fault-tolerant databases.
Microservices vs. Monolith: An Honest Architecture Decision Guide for 2026
A thorough analysis of when to choose microservices versus a monolithic architecture — covering organizational readiness, operational complexity, data consistency, service boundaries, and the strangler pattern for incremental migration.