Rate Limiting

Rate limiting caps how many requests a client can make in a window. It protects your API from abuse (credential stuffing, scraping), ensures fair resource sharing, and keeps the service stable when one client misbehaves or a bug hammers an endpoint.

It's both a security control and a reliability control — the same mechanism that blocks a brute-force attack also stops a runaway script from taking down the service for everyone else.

TL;DR

Quick Example

A baseline IP limiter in Express that emits standard headers and a clean 429:

Core Concepts

Algorithms

What to key on

How to respond

Return 429, a Retry-After (seconds), and RateLimit-Limit / RateLimit-Remaining / RateLimit-Reset so well-behaved clients can back off.

Best Practices

Use a shared store for distributed limits

In-memory counters break the moment you run more than one instance — each replica counts separately, so the real limit becomes instances × max. Use Redis (or an edge limiter) for a single source of truth. See Redis.

Tier by plan

Push limits to the edge when you can

A CDN/WAF (Cloudflare, AWS WAF) blocks floods before they reach your origin. Keep application-level limits too, for per-user fairness the edge can't see.

Common Mistakes

Counting in memory behind multiple instances

Rate limiting by IP behind a proxy

Returning 429 with no guidance

Always include Retry-After and RateLimit-* headers, so clients back off intelligently instead of retrying in a tight loop.

FAQ

Which algorithm should I use?

Token bucket is a great default — it allows short bursts while enforcing an average rate. Use a sliding window when you need smooth, boundary-free enforcement, and fixed window only when simplicity matters more than precision.

Where should counters live?

In a shared, fast store — Redis is the standard. In-memory only works for a single instance. For very high volume, enforce at the edge (CDN/WAF) and keep per-user limits in the app.

Should I limit by IP or by user?

Prefer the most specific identity available: API key or user ID for authenticated traffic, falling back to IP for anonymous requests. IP alone is coarse because many users share addresses behind NAT and proxies.

What status code and headers do I return?

429 Too Many Requests, plus Retry-After and the RateLimit-Limit/Remaining/Reset headers so clients know when to retry.

Related Topics

References