← Back to all snippets
JAVASCRIPT

Basic API Rate Limiting in Node.js Express

Implement a simple API rate limiting middleware in Node.js Express to protect your API endpoints from abuse and ensure fair usage by controlling the number of requests per client.

const express = require('express');
const app = express();
const PORT = process.env.PORT || 3000;

// In-memory store for rate limiting (for production, use Redis or similar)
const requestCounts = {};
const WINDOW_SIZE_MS = 60 * 1000; // 1 minute
const MAX_REQUESTS_PER_WINDOW = 5; // Max 5 requests per minute

/**
 * Simple rate limiting middleware
 * Limits requests based on IP address.
 * For production, use a more robust solution like 'express-rate-limit'
 * and a persistent store (Redis, Memcached).
 */
const rateLimitMiddleware = (req, res, next) => {
  // Use x-forwarded-for for production behind a proxy, otherwise req.ip
  const ip = req.headers['x-forwarded-for'] || req.ip;

  if (!requestCounts[ip]) {
    requestCounts[ip] = {
      count: 0,
      lastReset: Date.now()
    };
  }

  const client = requestCounts[ip];
  const currentTime = Date.now();

  // Reset count if window has passed
  if (currentTime - client.lastReset > WINDOW_SIZE_MS) {
    client.count = 0;
    client.lastReset = currentTime;
  }

  if (client.count >= MAX_REQUESTS_PER_WINDOW) {
    // Calculate how much time is left until reset
    const timeLeft = Math.ceil((client.lastReset + WINDOW_SIZE_MS - currentTime) / 1000);
    res.set('Retry-After', timeLeft); // Suggest client to retry after this many seconds
    return res.status(429).json({
      message: `Too many requests from this IP, please try again after ${timeLeft} seconds.`,
      retryAfter: timeLeft
    });
  }

  client.count++;
  next();
};

// Apply rate limiting to all API routes
app.use('/api', rateLimitMiddleware);

// Protected API endpoint
app.get('/api/data', (req, res) => {
  res.json({ message: 'This is some protected data!', timestamp: new Date() });
});

// Unprotected endpoint
app.get('/public', (req, res) => {
  res.json({ message: 'This is public data, no rate limit applies.' });
});

app.listen(PORT, () => {
  console.log(`Server running on port ${PORT}`);
});
How it works: This Node.js Express snippet demonstrates a basic, in-memory API rate limiting middleware. It tracks the number of requests made by each client's IP address within a defined time window (`WINDOW_SIZE_MS`). If a client exceeds `MAX_REQUESTS_PER_WINDOW` within that period, the middleware responds with a `429 Too Many Requests` HTTP status code and includes a `Retry-After` header. This prevents abuse, protects your API from being overwhelmed, and ensures fair access for all users. While this example uses an in-memory store (suitable for development or single-instance applications), production environments typically require a persistent store like Redis for distributed and scalable rate limiting.

Need help integrating this into your project?

Our team of expert developers can help you build your custom application from scratch.

Hire DigitalCodeLabs