Back to Tutorials

API Rate Limiting and Caching Strategies

Why Rate Limiting?

Rate limiting protects your API from abuse, ensures fair usage, and prevents server overload. It's essential for production APIs.

Implementing Rate Limiting

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

const app = express();

// Global rate limiter
const limiter = rateLimit({
  windowMs: 15 * 60 * 1000, // 15 minutes
  max: 100 // limit each IP to 100 requests per windowMs
});

app.use(limiter);

// Specific endpoint rate limiter
const strictLimiter = rateLimit({
  windowMs: 60 * 1000, // 1 minute
  max: 5 // 5 requests per minute
});

app.post('/api/login', strictLimiter, (req, res) => {
  // Login logic
});

// Rate limiter with Redis for distributed systems
const RedisStore = require('rate-limit-redis');
const redis = require('redis');
const client = redis.createClient();

const redisLimiter = rateLimit({
  store: new RedisStore({
    client: client
  }),
  windowMs: 15 * 60 * 1000,
  max: 100
});

API Caching

const redis = require('redis');
const client = redis.createClient();

// Cache middleware
async function cacheMiddleware(req, res, next) {
  const key = req.originalUrl;
  
  // Try to get from cache
  const cached = await client.get(key);
  if (cached) {
    return res.json(JSON.parse(cached));
  }
  
  // Store original json function
  const originalJson = res.json.bind(res);
  
  // Override json to cache response
  res.json = function(data) {
    // Cache for 5 minutes
    client.setex(key, 300, JSON.stringify(data));
    originalJson(data);
  };
  
  next();
}

// Use caching
app.get('/api/products', cacheMiddleware, async (req, res) => {
  const products = await Product.find();
  res.json(products);
});

Caching Strategies

  • Cache-Aside: Application checks cache, fetches from DB if miss
  • Write-Through: Write to cache and DB simultaneously
  • Write-Behind: Write to cache, async write to DB
  • TTL: Time-to-live for cache expiration

Best Practices

  • Set appropriate rate limits per endpoint
  • Use different limits for authenticated vs anonymous users
  • Implement caching for frequently accessed data
  • Invalidate cache on data updates
  • Monitor API usage and adjust limits accordingly