@fastify/rate-limit

Per-IP / Per-User Limits Out of the Box

@fastify/rate-limit

Track requests per key and return 429 responses with a Retry-After header. Use the built-in memory store for one process, or Redis for many.

4 min read Level 2/5 #fastify#rate-limit#security
What you'll learn
  • Install @fastify/rate-limit
  • Configure max requests and a timeWindow
  • Use the Redis store for multi-instance deployments

Rate limiting protects you from accidental client misuse and deliberate abuse. @fastify/rate-limit tracks request counts per key (the IP by default) and returns 429 with Retry-After once limits are exceeded.

Install & Register

npm install @fastify/rate-limit
import rateLimit from '@fastify/rate-limit'

await app.register(rateLimit, {
  max: 100,
  timeWindow: '1 minute',
})

That gives every IP 100 requests per minute. After that the plugin replies with 429 and a Retry-After header.

Redis for Multi-Instance

In-memory counters work for a single process. When you run multiple replicas, share state through Redis.

import Redis from 'ioredis'

await app.register(rateLimit, {
  redis: new Redis(app.config.REDIS_URL),
  max: 1000,
  timeWindow: '1 minute',
  nameSpace: 'rl:',
})

Per-User Keys

Keying by IP is unfair behind NATs. After you authenticate, key by user ID:

await app.register(rateLimit, {
  max: 600,
  timeWindow: '1 minute',
  keyGenerator: (req) => {
    const user = req.user as { sub?: string } | undefined
    return user?.sub ?? req.ip
  },
})

You can also attach a stricter limit to a single sensitive route with app.rateLimit({ max: 5, timeWindow: '1 minute' }) in config.

@fastify/multipart →