typescriptintermediate

In-Memory Rate Limiter for Express

Token bucket rate limiter middleware for Express with configurable window and max requests per IP.

typescript
import { Request, Response, NextFunction } from 'express';

interface RateBucket {
  tokens: number;
  lastRefill: number;
}

export function rateLimiter(opts: { windowMs?: number; max?: number } = {}) {
  const windowMs = opts.windowMs ?? 60_000;
  const max = opts.max ?? 100;
  const store = new Map<string, RateBucket>();

  setInterval(() => store.clear(), windowMs * 5);

  return (req: Request, res: Response, next: NextFunction) => {
    const key = req.ip ?? 'unknown';
    const now = Date.now();
    let bucket = store.get(key);

    if (!bucket) {
      bucket = { tokens: max, lastRefill: now };
      store.set(key, bucket);
    }

    const elapsed = now - bucket.lastRefill;
    const refill = Math.floor((elapsed / windowMs) * max);
    if (refill > 0) {
      bucket.tokens = Math.min(max, bucket.tokens + refill);
      bucket.lastRefill = now;
    }

    if (bucket.tokens <= 0) {
      res.set('Retry-After', String(Math.ceil(windowMs / 1000)));
      return res.status(429).json({ error: 'Too many requests' });
    }

    bucket.tokens--;
    res.set('X-RateLimit-Remaining', String(bucket.tokens));
    next();
  };
}

Use Cases

  • API abuse prevention
  • DDoS mitigation
  • Throttling public endpoints

Tags

Related Snippets

Similar patterns you can reuse in the same workflow.