What is express-rate-limit?
The express-rate-limit npm package is a middleware for Express applications that enables rate limiting to prevent abuse by restricting the number of requests a client can make in a given time frame. It is useful for preventing brute force attacks, DDoS attacks, and to generally control the traffic to an API or web application.
What are express-rate-limit's main functionalities?
Basic rate-limiting
This feature sets up basic rate-limiting on an Express application, limiting clients to a specified number of requests within a time frame.
const rateLimit = require('express-rate-limit');
const limiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15 minutes
max: 100 // limit each IP to 100 requests per windowMs
});
// Apply to all requests
app.use(limiter);
Custom message
This feature allows customization of the message sent back to the client when the rate limit is exceeded.
const rateLimit = require('express-rate-limit');
const limiter = rateLimit({
windowMs: 15 * 60 * 1000,
max: 100,
message: 'Too many requests, please try again later.'
});
app.use(limiter);
Skip certain requests
This feature allows some requests to bypass the rate limit, based on a condition such as a specific IP address.
const rateLimit = require('express-rate-limit');
const limiter = rateLimit({
windowMs: 15 * 60 * 1000,
max: 100,
skip: function (req, res) {
return req.ip === '123.123.123.123';
}
});
app.use(limiter);
Customize response headers
This feature enables sending HTTP headers to the client with information about their current rate limit status.
const rateLimit = require('express-rate-limit');
const limiter = rateLimit({
windowMs: 15 * 60 * 1000,
max: 100,
headers: true
});
app.use(limiter);
Other packages similar to express-rate-limit
ratelimiter
The 'ratelimiter' package is similar to 'express-rate-limit' but uses Redis for storing rate limit data, which makes it suitable for distributed applications. It is more complex to set up due to the dependency on Redis.
express-brute
The 'express-brute' package provides rate limiting with a focus on preventing brute-force attacks. It offers more customization options for handling lockouts and has a pluggable store system, which can be more flexible than 'express-rate-limit'.
express-slow-down
The 'express-slow-down' package is similar to 'express-rate-limit' but instead of blocking requests after a limit is reached, it slows down the response times. It's useful for slowing down repeated requests rather than completely blocking them.
Express Rate Limit
Basic rate-limiting middleware for Express. Use to limit repeated requests to public APIs and/or endpoints such as password reset.
Plays nice with express-slow-down.
Note: this module does not share state with other processes/servers by default.
If you need a more robust solution, I recommend using an external store:
Stores
- Memory Store (default, built-in) - stores hits in-memory in the Node.js process. Does not share state with other servers or processes.
- Redis Store
- Memcached Store
Alternate Rate-limiters
This module was designed to only handle the basics and didn't even support external stores initially. These other options all are excellent pieces of software and may be more appropriate for some situations:
Install
$ npm install --save express-rate-limit
Usage
For an API-only server where the rate-limiter should be applied to all requests:
const rateLimit = require("express-rate-limit");
app.enable("trust proxy");
const limiter = rateLimit({
windowMs: 15 * 60 * 1000,
max: 100
});
app.use(limiter);
For a "regular" web server (e.g. anything that uses express.static()
), where the rate-limiter should only apply to certain requests:
const rateLimit = require("express-rate-limit");
app.enable("trust proxy");
const apiLimiter = rateLimit({
windowMs: 15 * 60 * 1000,
max: 100
});
app.use("/api/", apiLimiter);
Create multiple instances to apply different rules to different routes:
const rateLimit = require("express-rate-limit");
app.enable("trust proxy");
const apiLimiter = rateLimit({
windowMs: 15 * 60 * 1000,
max: 100
});
app.use("/api/", apiLimiter);
const createAccountLimiter = rateLimit({
windowMs: 60 * 60 * 1000,
max: 5,
message:
"Too many accounts created from this IP, please try again after an hour"
});
app.post("/create-account", createAccountLimiter, function(req, res) {
});
A req.rateLimit
property is added to all requests with the limit
, current
, and remaining
number of requests for usage in your application code.
Configuration
- windowMs: milliseconds - how long to keep records of requests in memory. Defaults to
60000
(1 minute). - max: max number of connections during
windowMs
milliseconds before sending a 429 response. Defaults to 5
. Set to 0
to disable. - message: Error message returned when
max
is exceeded. Defaults to 'Too many requests, please try again later.'
- statusCode: HTTP status code returned when
max
is exceeded. Defaults to 429
. - headers: Enable headers for request limit (
X-RateLimit-Limit
) and current usage (X-RateLimit-Remaining
) on all responses and time to wait before retrying (Retry-After
) when max
is exceeded. - skipFailedRequests: when
true
failed requests (response status >= 400) won't be counted. Defaults to false
. - skipSuccessfulRequests: when
true
successful requests (response status < 400) won't be counted. Defaults to false
. - keyGenerator: Function used to generate keys. By default user IP address (req.ip) is used. Defaults:
function (req ) {
return req.ip;
}
- skip: Function used to skip requests. Returning true from the function will skip limiting for that request. Defaults:
function () {
return false;
}
- handler: The function to execute once the max limit is exceeded. It receives the request and the response objects. The "next" param is available if you need to pass to the next middleware. Defaults:
function (req, res, ) {
res.status(options.statusCode).send(options.message);
}
- onLimitReached: Function to listen each time the limit is reached. You can use it to debug/log. Defaults:
function (req, res, options) {
}
- store: The storage to use when persisting rate limit attempts. By default, the MemoryStore is used. It must implement the following in order to function:
function SomeStore() {
this.incr = function(key, cb) {
};
this.decrement = function(key) {
};
this.resetKey = function(key) {
};
}
Avaliable data stores are:
Instance API
- resetKey(key): Resets the rate limiting for a given key. (Allow users to complete a captcha or whatever to reset their rate limit, then call this method.)
v3 Changes
- Removed
delayAfter
and delayMs
options; they were moved to a new module: express-slow-down. - Simplified the default
handler
function so that it no longer changes the response format. Now uses res.send. onLimitReached
now only triggers once for a given ip and window. only handle
is called for every blocked request.
v2 Changes
v2 uses a less precise but less resource intensive method of tracking hits from a given IP. v2 also adds the limiter.resetKey()
API and removes the global: true
option.
License
MIT © Nathan Friedly