{"id":17436,"library":"express-rate-limit","title":"Express Rate Limiting Middleware","description":"express-rate-limit is a middleware for Express.js that provides basic IP-based rate limiting to protect endpoints from abuse, such as brute-force attacks on login or password reset forms, or excessive API requests. The current stable version is 8.3.2, and the package maintains an active release cadence, with multiple minor and patch updates within recent months, indicating ongoing development and support. Key differentiators include its flexible configuration for `windowMs` and `limit`, support for various external data stores (beyond its built-in memory store), and compliance with the IETF RateLimit header specification (draft-6, draft-7, and draft-8), allowing for modern and standardized rate limiting headers. It also includes `ipv6Subnet` configuration for granular IPv6 handling and integrates well with related packages like `express-slow-down`.","status":"active","version":"8.3.2","language":"javascript","source_language":"en","source_url":"https://github.com/express-rate-limit/express-rate-limit","tags":["javascript","express-rate-limit","express","rate","limit","ratelimit","rate-limit","middleware","ip","typescript"],"install":[{"cmd":"npm install express-rate-limit","lang":"bash","label":"npm"},{"cmd":"yarn add express-rate-limit","lang":"bash","label":"yarn"},{"cmd":"pnpm add express-rate-limit","lang":"bash","label":"pnpm"}],"dependencies":[{"reason":"Peer dependency, as this is an Express middleware.","package":"express","optional":false}],"imports":[{"note":"While CommonJS `require` still works, ESM `import` is the recommended and modern approach, especially for new projects. The package ships TypeScript types.","wrong":"const rateLimit = require('express-rate-limit')","symbol":"rateLimit","correct":"import { rateLimit } from 'express-rate-limit'"},{"note":"Type import for explicit TypeScript usage, enabling better type checking for middleware functions.","symbol":"RateLimitRequestHandler","correct":"import { type RateLimitRequestHandler } from 'express-rate-limit'"},{"note":"The default store is `MemoryStore`. If you need to explicitly reference or extend it, use `MemoryStore`. `Store` is an interface/abstract class.","wrong":"import { Store } from 'express-rate-limit'","symbol":"MemoryStore","correct":"import { MemoryStore } from 'express-rate-limit'"}],"quickstart":{"code":"import express from 'express';\nimport { rateLimit } from 'express-rate-limit';\n\nconst app = express();\n\n// Configure the rate limiter: 100 requests per IP every 15 minutes.\nconst apiLimiter = rateLimit({\n  windowMs: 15 * 60 * 1000, // 15 minutes\n  limit: 100, // Max 100 requests per IP per window\n  standardHeaders: 'draft-8', // Uses the latest IETF RateLimit header draft\n  legacyHeaders: false, // Disables the older X-RateLimit-* headers\n  message: 'Too many requests from this IP, please try again after 15 minutes.',\n  // store: new RedisStore({ /* ... config ... */ }), // Example of an external store\n});\n\n// Apply the rate limiting middleware to all API requests\napp.use('/api/', apiLimiter);\n\n// A public route that is not rate-limited\napp.get('/', (req, res) => {\n  res.send('Welcome! This route is not rate-limited.');\n});\n\n// A rate-limited API endpoint\napp.get('/api/data', (req, res) => {\n  res.json({ message: 'This is some data.' });\n});\n\nconst PORT = process.env.PORT || 3000;\napp.listen(PORT, () => {\n  console.log(`Server running on port ${PORT}`);\n});\n","lang":"typescript","description":"This quickstart demonstrates how to set up a basic rate limit for all requests under '/api/' using the `rateLimit` middleware, configuring its window, limit, and modern headers."},"warnings":[{"fix":"Consult the official changelog for v8.0.0. Update `standardHeaders` to 'draft-8' for the latest spec, or 'draft-6' for an older one. Set `legacyHeaders: false` to disable the deprecated `X-RateLimit-*` headers if not needed for backwards compatibility.","message":"Version 8.0.0 introduced breaking changes. Specifically, the library shifted towards adhering more closely to IETF RateLimit header specifications. Review your configuration, especially `standardHeaders` and `legacyHeaders`.","severity":"breaking","affected_versions":">=8.0.0"},{"fix":"For production deployments, configure an external `store` like Redis or Memcached to ensure consistent rate limiting across all instances. Refer to the 'Data Stores' section in the documentation.","message":"By default, `express-rate-limit` uses a `MemoryStore`. In production environments with multiple Node.js instances or processes, this can lead to inconsistent rate limiting as each instance will have its own independent hit count.","severity":"gotcha","affected_versions":">=1.0.0"},{"fix":"Carefully choose an appropriate `ipv6Subnet` value (e.g., 60 or 64 for typical home networks, 52 or 48 for more aggressive limiting) based on your network architecture and desired behavior. The default might not be suitable for all use cases.","message":"The `ipv6Subnet` option is crucial for correctly identifying unique users on IPv6 networks. An incorrect setting can either be too aggressive (treating many users in a subnet as one) or too lenient (allowing more requests than intended).","severity":"gotcha","affected_versions":">=6.0.0"},{"fix":"Set `standardHeaders` to `'draft-8'` (or `'draft-6'/'draft-7'` if needed for older clients) and consider setting `legacyHeaders: false` to embrace the modern standard. Inform clients about the header change.","message":"The traditional `X-RateLimit-*` headers are considered legacy. While still supported via the `legacyHeaders: true` option, the library encourages adoption of the IETF RateLimit header specification.","severity":"deprecated","affected_versions":">=7.5.0"}],"env_vars":null,"last_verified":"2026-04-22T00:00:00.000Z","next_check":"2026-07-21T00:00:00.000Z","problems":[{"fix":"Ensure you are using named import: `import { rateLimit } from 'express-rate-limit'` for ESM, or `const { rateLimit } = require('express-rate-limit')` for CommonJS. Do not use `new` with `rateLimit`.","cause":"Attempting to use `new rateLimit()` or incorrectly importing the function, especially in CommonJS where the default export might be expected directly.","error":"TypeError: rateLimit is not a function"},{"fix":"Ensure that the `store` option is provided with an instantiated store object, e.g., `store: new RedisStore({ client: redisClient })`.","cause":"The `store` option was specified but its value was `undefined` or `null`, often due to an uninitialized external store instance.","error":"Error: Store must be defined (if using a custom store with 'store' option)"},{"fix":"Verify that `app.use(limiter)` is called *before* the routes you intend to limit. If limiting specific routes, apply `app.get('/route', limiter, handler)` instead of globally. Check your `windowMs` and `limit` values are not excessively high.","cause":"The middleware might be applied globally when it should be route-specific, or vice-versa, or applied in the wrong order in your Express middleware chain.","error":"Rate limiting not being applied or not working as expected (e.g., still receiving 200 OK after many requests)"}],"ecosystem":"npm","meta_description":null}