API Rate Limiting: Protecting Your Express Endpoints
Rate limiting acts as a bouncer for your API, preventing any single user from overwhelming it. It's crucial for public APIs and sensitive endpoints like password resets to block abuse. The default in-memory store won't work across multiple server instances.
WHY IT EXISTS Publicly exposed APIs are vulnerable to abuse, whether intentional (denial-of-service attacks, brute-forcing passwords) or unintentional (a buggy client sending requests in a tight loop). Rate limiting provides a first line of defense by restricting how many requests a single client can make in a given time frame, preserving resources for legitimate users.
THE MENTAL MODEL Think of rate limiting as a bouncer at a club door with a clicker. The bouncer (the middleware) allows a certain number of people (requests) from the same group (a single IP address) into the club (your API) within a set time period (the window). Once the limit is hit, the bouncer tells everyone else from that group to wait outside until the next time period begins, typically by sending a 429 Too Many Requests response.
HOW IT WORKS When a request arrives, the express-rate-limit middleware identifies the client, usually by IP address. It then consults a data store to check how many requests this client has made within the configured time window (windowMs). If the count is below the limit, the middleware increments the count and passes the request to your application logic. If the limit is reached, it blocks the request and sends a 429 response. This state (the count for each IP) is held in a store, which is in-memory by default but can and should be an external store like Redis or Memcached for production applications.
WHEN TO USE IT Use rate limiting on any public-facing API to ensure fair use and prevent abuse. It is especially critical for sensitive endpoints like login, registration, or password reset to protect against brute-force and credential stuffing attacks. It's also essential for any API that is resource-intensive to prevent a few clients from degrading service for everyone.
WHEN NOT TO USE IT Rate limiting might be overkill for purely internal services where all clients are trusted and traffic is predictable. The main footgun is misconfiguration: setting limits too low can block legitimate users, especially those behind a shared network (like a corporate office or university) that makes many users appear to come from a single IP address.
ONE CANONICAL EXAMPLE The following express-rate-limit configuration allows each IP address to make 100 requests every 15 minutes. After the 101st request within that window, the user will be blocked and receive a 429 status code until the 15-minute window resets.
import { rateLimit } from 'express-rate-limit'
const limiter = rateLimit({ windowMs: 15 * 60 * 1000, // The time window: 15 minutes in milliseconds limit: 100, // Max requests per IP per window standardHeaders: 'draft-8', // Send modern RateLimit header legacyHeaders: false, // Disable old X-RateLimit-* headers });
// Apply to all requests app.use(limiter);
Read the original → github.com
Get five bites like this every day.
Tezvyn delivers a daily feed of 60-second tech bites with quizzes to lock in what you learn.