Rate Limiting in Fastify That Actually Works

@fastify/rate-limit + Redis is the production-grade combo. Here's the config that handles trust proxy, per-route limits, and per-user keys correctly.

May 9, 2026·4 min read

Rate Limiting in Fastify That Actually Works

@fastify/rate-limit is the standard. Here's the production config.

Setup

npm install @fastify/rate-limit ioredis
import Fastify from 'fastify';
import rateLimit from '@fastify/rate-limit';
import Redis from 'ioredis';

const app = Fastify({ trustProxy: 1 });

await app.register(rateLimit, {
  global: true,
  max: 100,
  timeWindow: '1 minute',
  redis: new Redis(process.env.REDIS_URL),
  keyGenerator: (req) => {
    const user = (req).user; // if you've set this in an auth hook
    return user?.id || req.ip;
  },
  skipOnError: true, // fail open if Redis is down
});

Per-route limits

Stricter on auth routes:

app.post('/auth/login', {
  config: {
    rateLimit: {
      max: 5,
      timeWindow: '5 minutes',
    },
  },
}, async (req, reply) => {
  // login handler
});

What skipOnError does

When Redis is unreachable, the rate limiter fails open by default — requests pass through unrestricted. This prevents Redis becoming a hard dependency for your app's availability. Tradeoff: during a Redis outage, rate limits are temporarily disabled.

Verifying

for i in {1..15}; do curl -i http://localhost:3000/auth/login -d 'foo'; done

After the limit, you'll see 429 Too Many Requests with X-RateLimit-* headers indicating when to retry.

Frequently Asked Questions

Does @fastify/rate-limit support per-route limits?

Yes — pass a config object to specific routes via `config.rateLimit`. Different limits per endpoint without separate plugin registrations.

Should I use the built-in store or Redis?

Redis for multi-instance. The built-in LRU store is in-memory and per-process.

What about per-user rate limiting?

Pass a `keyGenerator` function that returns the user ID for authenticated requests, falling back to IP.

Recommended reading

Block an IP, a Range or One Route Without a Deploy (Node.js)

Block one IP, a CIDR range, or a single route and method in a Node.js app within seconds, with no code change: setup, scoping, CLI, MCP, verification and undo.

Oct 27
11 Signs Your AI-Built App Needs a Security Audit

Built your app with a coding agent? 11 warning signs it needs a security audit, each checkable in five minutes, and how to run the full audit yourself.

Oct 26
AI Security Audit Part 1: Set Up Your Agent to Audit Code

Part 1 of the AI security audit series: set up an AI coding agent to audit your app locally, connect SecureNow, and run your first threat-model pass.

Jul 24