What is Rate Limiting?

Download this article as a PDF on the Codeflare Mobile App

Rate limiting restricts the number of requests a client can make within a specific time window.

Example:

  • Max: 100 requests per 15 minutes per IP
  • If exceeded → request is blocked (usually with 429 Too Many Requests)

Why it matters:

  • Prevents brute-force attacks
  • Stops API abuse
  • Protects server resources
  • Ensures fair usage across users

What is Throttling?

Throttling controls the rate at which requests are processed, often by slowing them down rather than blocking them outright.

Learn on the Go. Download the Codeflare Mobile App from Google Play Store

Example:

  • Allow 1 request per second
  • Extra requests are delayed or queued

Key difference:

FeatureRate LimitingThrottling
BehaviorBlocks excess requestsSlows them down
Response429 errorDelayed response
Use caseSecurity & abuse controlTraffic shaping & smoothing

Core Algorithms Behind Rate Limiting

Understanding these helps you design custom systems.

1. Fixed Window Counter

  • Count requests in a fixed time window (e.g., per minute)
  • Simple but can cause bursts

👉 Problem: A user can send many requests at the boundary

2. Sliding Window Log

  • Stores timestamps of requests
  • More accurate but memory-heavy

3. Sliding Window Counter

  • Hybrid approach (more efficient than logs)

4. Token Bucket (Best for Throttling)

  • Tokens are added at a steady rate
  • Requests consume tokens
  • If no tokens → wait or reject

5. Leaky Bucket

  • Requests are processed at a fixed rate
  • Excess requests are queued or dropped

Implementing Rate Limiting in Node.js

1. Using express-rate-limit (Most Common)

Install:

npm install express-rate-limit

Basic Setup:

const express = require('express');
const rateLimit = require('express-rate-limit');

const app = express();

const limiter = rateLimit({
  windowMs: 15 * 60 * 1000, // 15 minutes
  max: 100, // limit each IP
  message: 'Too many requests, try again later',
  standardHeaders: true,
  legacyHeaders: false,
});

app.use('/api', limiter);

app.get('/api/data', (req, res) => {
  res.send('API response');
});

app.listen(3000);

2. Advanced Rate Limiting with Redis (Production Ready)

For distributed systems (multiple servers), in-memory limits won’t work.

Use Redis.

Install:

npm install rate-limiter-flexible ioredis

Example:

const { RateLimiterRedis } = require('rate-limiter-flexible');
const Redis = require('ioredis');

const redisClient = new Redis();

const rateLimiter = new RateLimiterRedis({
  storeClient: redisClient,
  points: 10, // 10 requests
  duration: 1, // per second
});

const express = require('express');
const app = express();

app.use(async (req, res, next) => {
  try {
    await rateLimiter.consume(req.ip);
    next();
  } catch {
    res.status(429).send('Too Many Requests');
  }
});

3. Implementing Throttling (Custom Logic)

Simple Delay Throttling:

const delay = (ms) => new Promise(resolve => setTimeout(resolve, ms));

app.use(async (req, res, next) => {
  await delay(500); // delay each request
  next();
});

4. Token Bucket Example

class TokenBucket {
  constructor(capacity, refillRate) {
    this.capacity = capacity;
    this.tokens = capacity;
    this.refillRate = refillRate;
    this.lastRefill = Date.now();
  }

  refill() {
    const now = Date.now();
    const diff = (now - this.lastRefill) / 1000;
    this.tokens = Math.min(this.capacity, this.tokens + diff * this.refillRate);
    this.lastRefill = now;
  }

  consume() {
    this.refill();
    if (this.tokens >= 1) {
      this.tokens -= 1;
      return true;
    }
    return false;
  }
}

Best Practices for Node.js Apps

1. Use IP + User-Based Limiting

  • Combine IP + API key / user ID
  • Prevent shared IP abuse

2. Different Limits per Route

app.use('/login', strictLimiter);
app.use('/api', generalLimiter);

3. Protect Sensitive Endpoints

  • Login
  • Password reset
  • Payment APIs

4. Use Headers for Transparency

X-RateLimit-Limit: 100
X-RateLimit-Remaining: 20

5. Graceful Handling

Return helpful errors:

{
  "error": "Too many requests",
  "retry_after": "60 seconds"
}

6. Combine with Other Security Layers

  • CAPTCHA
  • API keys
  • Authentication (JWT)
  • WAF (Cloudflare in for apps like Codeflare)

Real-World Use Cases

1. Login Protection

  • 5 attempts per minute
  • Prevent brute-force attacks

2. Public APIs

  • Free tier: 100 requests/hour
  • Paid tier: 1000 requests/hour

3. Payment Systems

  • Strict throttling to prevent fraud spikes

4. Scraping Prevention

  • Detect unusual request bursts

⚠️ Common Pitfalls

  • ❌ Using in-memory limiter in distributed apps
  • ❌ Not handling proxies (X-Forwarded-For)
  • ❌ Blocking legitimate users (too strict limits)
  • ❌ Ignoring burst traffic patterns

Conclusion

  • Rate limiting = control how many requests are allowed
  • Throttling = control how fast requests are processed
  • Both are critical for:
    • Security
    • Performance
    • Scalability
Share
Published by
codeflare

Recent Posts

JavaScript promise chaining

Learn on the Go. Download the Codeflare Mobile from iOS App Store.  1. What is…

3 days ago

UI/UX Design — Explained Like You’re 5

Download the Codeflare iOS app and learn on the Go 1. What UI and UX…

3 weeks ago

Costly Linux Mistakes Beginners Make

1. Running Everything as Root One of the biggest beginner errors. Many new users log…

2 months ago

How Keyloggers Work

A keylogger is a type of surveillance software or hardware that records every keystroke made…

2 months ago

JavaScript Memoization

In JavaScript, it’s commonly used for: Recursive functions (like Fibonacci) Heavy calculations Repeated API/data processing…

3 months ago

CSS Container Queries: Responsive Design That Actually Makes Sense

For years, responsive design has depended almost entirely on media queries. We ask questions like: “If…

3 months ago