Back to Snippets
Node.jsTypeScript

Node.js Rate Limiter

An in-memory rate limiter middleware to protect APIs from abuse.

nodejsrate limitapisecurity
import type { Request, Response, NextFunction } from class=class="text-emerald-400">"text-emerald-400">'express'

interface RateLimitEntry {
  count: number
  resetAt: number
}

function createRateLimiter(options: { windowMs: number; max: number }) {
  const { windowMs, max } = options
  const store = new Map<string, RateLimitEntry>()

  class=class="text-emerald-400">"text-gray">// Cleanup expired entries every minute
  setInterval(() => {
    const now = Date.now()
    for (const [key, entry] of store) {
      if (entry.resetAt < now) store.delete(key)
    }
  }, 60_000)

  return (req: Request, res: Response, next: NextFunction) => {
    const key = req.ip || class=class="text-emerald-400">"text-emerald-400">'unknown'
    const now = Date.now()
    const entry = store.get(key)

    if (!entry || entry.resetAt < now) {
      store.set(key, { count: 1, resetAt: now + windowMs })
      return next()
    }

    if (entry.count >= max) {
      res.set(class=class="text-emerald-400">"text-emerald-400">'Retry-After', String(Math.ceil((entry.resetAt - now) / 1000)))
      return res.status(429).json({ error: class=class="text-emerald-400">"text-emerald-400">'Too many requests' })
    }

    entry.count++
    next()
  }
}

export const apiLimiter = createRateLimiter({ windowMs: 60_000, max: 100 })

How to Use

Apply to routes: app.use('/api', apiLimiter). It allows 100 requests per minute per IP. For production, replace the Map store with Redis for multi-instance support.

Related Technology

Node.js

Have a Project in Mind?

Let's discuss how we can bring your idea to life. From initial concept to production-ready product — we've got you covered.

or book a free call