---
title: 'Configuration'
icon: 'bars-staggered'
---

No configuration is required, all options have reasonable defaults.

Any option that may be set to a function may also be set to an async function,
or to a function that returns a promise. Async functions and promises will be
awaited for the value.

## `windowMs`

> `number`

Time frame for which requests are checked/remembered. The time window for each
user starts at their first request. After it elapses, the user's hit count is
reset to zero. A new time window is then started on their next request.

Also used in the `Retry-After` header when the limit is reached.

This value **cannot** be set to a function. If multiple time windows are needed,
create multiple rate limiters.

<Note>

For stores that do not implement the `init` function (including all legacy
stores - see the [data stores page][stores]), you may need to configure this
value twice, once here and once on the store. In some cases the units also
differ (e.g. seconds vs milliseconds).

</Note>

Maximum value with the default MemoryStore is `2147483647` (2^31-1, ~28.4 days)
due to
[limitations of the `setInterval()` call in node.js](https://nodejs.org/api/timers.html#setintervalcallback-delay-args).
(Also, all rate limits in the default MemoryStore are reset when the node.js
process is restarted.) Most other [stores] support larger values and retain
their state when node.js is reset.

Defaults to `60000` ms (= 1 minute).

### Time constants

Constants for `DAY`, `HOUR`, `MINUTE`, and `SECOND` are provided to make the
`windowMs` configuration a little easier to work with.

For example, to set a 3 hour window:

```ts
import { rateLimit, HOUR } from 'express-rate-limit'

const limiter = rateLimit({
	windowMs: 3 * HOUR,
	// ...
})
```

Or, for a 1 minute and 30 second window:

```ts
import { rateLimit, MINUTE, SECOND } from 'express-rate-limit'

const limiter = rateLimit({
	windowMs: 1 * MINUTE + 30 * SECOND,
	// ...
})
```

## `limit`

> `number | function`
>
> Renamed in v7.x from `max` to `limit`. However, `max` will still be supported
> for backwards-compatibility.

The maximum number of connections to allow during the `window` before rate
limiting the client.

Can be the limit itself as a number or a (sync/async) function that accepts the
Express `req` and `res` objects and then returns a number.

<Warning>

As of version 7.0.0, setting `max` to zero will no longer disable the rate
limiter - instead, it will 'block' all requests to that endpoint.

</Warning>

Defaults to `5`.

An example of using a function:

```ts
const isPremium = async (user) => {
	// ...
}

const limiter = rateLimit({
	// ...
	limit: async (req, res) => {
		if (await isPremium(req.user)) return 10
		else return 5
	},
})
```

## `message`

> `any`

The response body to send back when a client is rate limited.

May be a string, JSON object, or any other value that Express's
[res.send](https://expressjs.com/en/4x/api.html#res.send) method supports. It
can also be a (sync/async) function that accepts the Express request and
response objects and then returns a `string`, JSON object, etc.

Defaults to `'Too many requests, please try again later.'`

An example of sending a JSON object:

```js
app.use(
	rateLimit({
		message: { error: 'Too many requests, please try again later.' },
		// ...
	}),
)
```

An example of using a function:

```ts
const isPremium = async (user) => {
	// ...
}

const limiter = rateLimit({
	// ...
	message: async (req, res) => {
		if (await isPremium(req.user))
			return 'You can only make 10 requests every hour.'
		else return 'You can only make 5 requests every hour.'
	},
})
```

Set a custom [`handler`](#handler) for more advanced use-cases, such as using
[`res.render()`](http://expressjs.com/en/4x/api.html#res.render) to send a
templated response.

## `statusCode`

> `number`

The HTTP status code to send back when a client is rate limited.

Defaults to `429`.

<Note>

The HTTP status code `429` is defined in
[section 4](https://datatracker.ietf.org/doc/html/rfc6585#section-4) of IETF's
RFC 6585.

</Note>

## `handler`

> `function`

Express request handler that sends back a response when a client is
rate-limited.

By default, sends back the `statusCode` and `message` set via the `options`,
similar to this:

```ts
const limiter = rateLimit({
	// ...
	handler: (req, res, next, options) =>
		res.status(options.statusCode).send(options.message),
})
```

## `legacyHeaders`

> `boolean`
>
> Renamed in `6.x` from `headers` to `legacyHeaders`.

Whether to send the legacy rate limit headers for the limit
(`X-RateLimit-Limit`), current usage (`X-RateLimit-Remaining`) and reset time
(if the store provides it) (`X-RateLimit-Reset`) on all responses. If set to
`true`, the middleware also sends the `Retry-After` header on all blocked
requests.

Defaults to `true`.

<Note>

Note that this option only defaults to `true` for backward compatibility, and it
is recommended to set it to `false` and use `standardHeaders` instead.

</Note>

## `standardHeaders`

> `boolean` | `'draft-6'` | `'draft-7'` | `'draft-8'`
>
> Renamed in `6.x` from `draft_polli_ratelimit_headers` to `standardHeaders`.

Whether to enable support for headers conforming to the
[RateLimit header fields for HTTP standardization draft](https://github.com/ietf-wg-httpapi/ratelimit-headers)
adopted by the IETF.

If set to `draft-6`, separate `RateLimit-Policy` `RateLimit-Limit`,
`RateLimit-Remaining`, and, if the store supports it, `RateLimit-Reset` headers
are set on the response, in accordance with the
[sixth draft](https://datatracker.ietf.org/doc/html/draft-ietf-httpapi-ratelimit-headers-06)
of the IETF rate limit header specification.

If set to `draft-7`, a combined `RateLimit` header is set containing limit,
remaining, and reset values, and a `RateLimit-Policy` header is set, in
accordance with the
[seventh draft](https://datatracker.ietf.org/doc/html/draft-ietf-httpapi-ratelimit-headers-07)
of the IETF rate limit header specification. `windowMs` is used for the reset
value if the store does not provide a reset time.

If set to `draft-8`, a combined `RateLimit` header is set containing the
remaining and reset values, along with a `RateLimit-Policy` header, is set for
each rate limiter defined, in accordance with the
[eighth draft](https://datatracker.ietf.org/doc/html/draft-ietf-httpapi-ratelimit-headers-08)
of the IETF rate limit header specification. The value of `windowMs` is used for
the reset parameter if the store does not provide a reset time.

Note that the
[ninth draft](https://datatracker.ietf.org/doc/html/draft-ietf-httpapi-ratelimit-headers-09)
of the IETF rate limit header specification does not specify any changes in the
function or format of the headers. Set this option to `draft-8` for the same.

<Warning>

If set to generate `draft-7` or `draft-8` headers, make sure that you are using
Express `v4.11` or later, as the implementation of these two drafts requires the
`response.append` function.

</Warning>

If set to `true`, it is treated as `draft-6`, however, this behavior may change
in a future semver major release.

If set to any truthy value, the middleware also sends the `Retry-After` header
on all blocked requests.

The `standardHeaders` option may be used in conjunction with, or instead of the
`legacyHeaders` option.

<Note>

Tip: use the
[ratelimit-header-parser](https://www.npmjs.com/package/ratelimit-header-parser)
library in clients to read/parse any form of headers.

</Note>

Defaults to `false`.

## `identifier`

> `string | function`

The name associated with the quota policy that this instance of the rate limiter
enforces. It is used in the `RateLimit` and `RateLimit-Policy` headers when
`standardHeaders` is set to `draft-8`, and ignored otherwise.

Can be the identifier itself as a string or a (sync/async) function that accepts
the Express `req` and `res` objects and then returns a string.

Defaults to a function that returns a string of the format
`{limit}-in-{window}`, e.g., `7-in-1.5sec`.

## `store`

> `Store`

The `Store` to use to store the hit count for each client.

By default, the
[`memory-store`](https://github.com/express-rate-limit/express-rate-limit/blob/main/source/memory-store.ts)
is used.

See [Data Stores](/reference/stores) for a list of avalliable stores and other
information.

## `passOnStoreError`

By default, this is `false` and express-rate-limit will call the
[express error handler](http://expressjs.com/en/guide/error-handling.html#error-handling)
in the event of a store error. In other words, the default is to "fail closed"
and block all requests if the datastore becomes unavailable.

Set this to `true` to "fail open" allow the request(s) through without rate
limiting. The error will be logged in this case.

## `keyGenerator`

> `function`

Method to retrieve custom identifiers for clients, such as their IP address,
username, or API Key.

Should be a (sync/async) function that accepts the Express `request` and
`response` objects and then returns a string.

By default, the client's IP address is used with the
[`ipKeyGenerator`](./helpers#ipkeygenerator) method to apply the configured
[`ipv6Subnet`](#ipv6subnet) to IPv6 addresses.

Custom `keyGenerator`s that fall back to IP addresses should use the provided
[`ipKeyGenerator`](./helpers#ipkeygenerator) method and a chosen subnet for IPv6
addresses (see [ipv6Subnet](#ipv6subnet) discussion below.)

```ts
import { rateLimit, ipKeyGenerator } from 'express-rate-limit'
const limiter = rateLimit({
	// ...
	keyGenerator: (req, res) => ipKeyGenerator(req.ip),
})
```

<Note>

If a `keyGenerator` returns the same value for every user, it becomes a global
rate limiter. This could be combined with a second instance of
`express-rate-limit` to have both global and per-user limits.

</Note>

## `ipv6Subnet`

> `number` (32-64) | `function` | `false`

IPv6 subnet mask applied to IPv6 addresses in the default
[`keyGenerator`](#keygenerator).

Generally, ISPs that support IPv6 give each of their customers a range of IPv6
addresses via a subnet mask, whereas they usually provide only a single IPv4
address per customer. A malicious user could iterate through their range of IPv6
addresses and bypass simple IP-based rate limiting. This setting counteracts
that by allowing the rate-limiter to block an entire range of IPv6 addresses at
once.

It's generally not possible to know what subnet an ISP has assigned to a user,
so we have to make an educuated guess.

The default value is 56, corresponding to a /56 subnet.

The valid range is 1-128, but typically ISPs assign subnets in the range of
32-64, with 64 being the most common. The validation check (which can be
disabled) will warn for values outside the 32-64 range.

Smaller values block larger ranges of IPs at once. 56 is a moderately aggressive
default. It may be increased to if users are being incorrectly blocked (try 60
or 64), or decreased if you are seeing evidence of abuse.

64, 60 ([Comcast](https://news.ycombinator.com/item?id=44228908)), 56, and 48
are all common values used by various ISPs.

The option may also be set to a function that returns the value if you want to
apply different subnets to different users. (It's not always possible to know
what subnet a given user has, but you could make an educuated guess based on
their ISP - see the example below.)

Set to false to disable and always use the IP without masking.

This example uses the node.js built-in
[`net.BlockList`](https://nodejs.org/api/net.html#class-netblocklist) to apply
different subnets to different IP ranges:

```js
import { BlockList } from 'node:net'
// or
// const { BlockList } = require('node:net')

// Comcast defaults to /64 but allows customers to request /60
// (note that this is a non-exhaustive list, there are many more)
const networks60 = new BlockList()
networks60.addSubnet('2a0c:93c0:10::', 44, 'ipv6')
networks60.addSubnet('2a0c:93c0:6000::', 48, 'ipv6')
networks60.addSubnet('2a0c:93c0:6002::', 48, 'ipv6')

// AWS allows customers to request up to a /44!
// (the full list is at https://ip-ranges.amazonaws.com/ip-ranges.json)
const networks44 = new BlockList()
networks44.addSubnet('2600:1f69:7400::', 40, 'ipv6')

app.use(
	rateLimit({
		ipv6Subnet: function (req, res) {
			if (networks60.check(req.ip, 'ipv6')) return 60
			if (networks44.check(req.ip, 'ipv6')) return 44
			return 56 // fallback
		},
		// ...
	}),
)
```

## `requestPropertyName`

> `string`

The name of the property on the Express `request` object to store the rate limit
info.

Defaults to `'rateLimit'`.

## `skip`

> `function`

Function to determine whether or not this request counts towards a client's
quota. Should be a (sync/async) function that accepts the Express `request` and
`response` objects and then returns `true` or `false`.

Could also act as an allowlist for certain keys:

```ts
const allowlist = ['192.168.0.56', '192.168.0.21']

const limiter = rateLimit({
	// ...
	skip: (req, res) => allowlist.includes(req.ip),
})
```

By default, it skips no requests:

```ts
const limiter = rateLimit({
	// ...
	skip: (req, res) => false,
})
```

## `skipSuccessfulRequests`

> `boolean`

If `true`, the library will (by default) skip all requests that are considered
'failed' by the `requestWasSuccessful` function. By default, this means requests
succeed when the response status code less than `400`.

<Note>

Technically, the requests are counted and then un-counted, so a large number of
slow requests all at once could still trigger a rate-limit. This may be fixed in
a future release. PRs welcome!

</Note>

Defaults to `false`.

## `skipFailedRequests`

> `boolean`

When set to `true`, failed requests won't be counted. Request considered failed
when the `requestWasSuccessful` option returns `false`. By default, this means
requests fail when:

- the response status >= `400`
- the request was cancelled before last chunk of data was sent (response `close`
  event triggered)
- the response `error` event was triggered by response

<Note>

Technically, the requests are counted and then un-counted, so a large number of
slow requests all at once could still trigger a rate-limit. This may be fixed in
a future release. PRs welcome!

</Note>

Defaults to `false`.

## `requestWasSuccessful`

> `function`

Method to determine whether or not the request counts as 'successful'. Used when
either `skipSuccessfulRequests` or `skipFailedRequests` is set to true. Should
be a (sync/async) function that accepts the Express `req` and `res` objects and
then returns `true` or `false`.

By default, requests with a response status code less than `400` are considered
successful:

```ts
const limiter = rateLimit({
	// ...
	requestWasSuccessful: (req, res) => res.statusCode < 400,
})
```

## `validate`

> `boolean | Object`

When enabled, a set of validation checks are run early on to detect common
misconfigurations with proxies, etc. Prints an error to the console if any issue
is detected.

If set to `true` or `false`, all validations are enabled or disabled.

If set to an object, individual validations can be enabled or disabled by name,
and the key `default` controls all unspecified validations. For example:

```js
const limiter = rateLimit({
	validate: {
		xForwardedForHeader: false,
		default: true,
	},
	// ...
})
```

Supported validations are:

- [ip](/reference/error-codes#err-erl-undefined-ip-address)
- [trustProxy](/reference/error-codes#err-erl-permissive-trust-proxy)
- [xForwardedForHeader](/reference/error-codes#err-erl-unexpected-x-forwarded-for)
- [forwardedHeader](/reference/error-codes#err-erl-forwarded-header)
- [positiveHits](/reference/error-codes#err-erl-invalid-hits)
- [unsharedStore](/reference/error-codes#err-erl-store-reuse)
- [singleCount](/reference/error-codes#err-erl-double-count)
- [limit](/reference/error-codes#wrn-erl-max-zero)
- [draftPolliHeaders](/reference/error-codes#wrn-erl-deprecated-draft-polli-headers)
- [onLimitReached](/reference/error-codes#wrn-erl-deprecated-on-limit-reached)
- [headersDraftVersion](/reference/error-codes#err-erl-headers-unsupported-draft-version)
- [headersResetTime](/reference/error-codes#err-erl-headers-no-reset)
- [creationStack](/reference/error-codes#err-erl-created-in-request-handler)
- [knownOptions](/reference/error-codes)
- [validationsConfig](/reference/error-codes#err-erl-unknown-validation)
- [ipv6Subnet](/reference/error-codes#err-erl-ipv6-subnet)
- [ipv6SubnetOrKeyGenerator](/reference/error-codes#err-erl-ipv6subnet-or-keygenerator)
- [keyGeneratorIpFallback](/reference/error-codes#err-erl-key-gen-ipv6)
- [windowMs](/reference/error-codes#err-erl-window-ms)

Defaults to `true`.

[stores]: /reference/stores

## `logger`

> `Logger`

The Logger instance to use to log validation errors or warnings. Default
behavior is to use the console. The first argument is the error that was raised,
the second is an optional message explaining the error. For example:

```js
const limiter = rateLimit({
	logger: {
		warn: (error, message) => {
			// TODO: do something with error and message
		},
		error: (error, message) => {
			// TODO: do something with error and message
		},
	},
})
```

## Debug logging

Debug logging is controlled via the `DEBUG` environment property rather than a
configuration option. See [Debugging Express Rate Limit](/guides/debugging) for
additional details.
