# Configuration Options

This document provides comprehensive details on all configuration options available for express-rate-limit.

## Core Configuration

```typescript { .api }
interface Options {
  windowMs: number;
  limit: number | ValueDeterminingMiddleware<number>;
  message: any | ValueDeterminingMiddleware<any>;
  statusCode: number;
  legacyHeaders: boolean;
  standardHeaders: boolean | DraftHeadersVersion;
  identifier: string | ValueDeterminingMiddleware<string>;
  requestPropertyName: string;
  skipFailedRequests: boolean;
  skipSuccessfulRequests: boolean;
  keyGenerator: ValueDeterminingMiddleware<string>;
  ipv6Subnet: number | ValueDeterminingMiddleware<number> | false;
  handler: RateLimitExceededEventHandler;
  skip: ValueDeterminingMiddleware<boolean>;
  requestWasSuccessful: ValueDeterminingMiddleware<boolean>;
  store: Store | LegacyStore;
  validate: boolean | EnabledValidations;
  passOnStoreError: boolean;
}
```

## Time and Limit Configuration

### windowMs
**Type:** `number`  
**Default:** `60000` (1 minute)

Duration in milliseconds for which requests are checked/remembered.

```typescript
const limiter = rateLimit({
  windowMs: 15 * 60 * 1000, // 15 minutes
  limit: 100
});
```

### limit
**Type:** `number | ValueDeterminingMiddleware<number>`  
**Default:** `5`

Maximum number of requests allowed during the window. Can be a static number or a function that dynamically determines the limit based on the request.

```typescript
// Static limit
const limiter = rateLimit({
  limit: 100
});

// Dynamic limit based on user type
const dynamicLimiter = rateLimit({
  limit: async (req, res) => {
    if (req.user?.isPremium) return 1000;
    return 100;
  }
});
```

## Response Configuration

### message
**Type:** `any | ValueDeterminingMiddleware<any>`  
**Default:** `"Too many requests, please try again later."`

Response body sent when rate limit is exceeded. Can be a string, object, or function.

```typescript
const limiter = rateLimit({
  message: "Rate limit exceeded. Try again later.",
  // or as JSON
  message: {
    error: "Too many requests",
    retryAfter: "15 minutes"
  },
  // or as function
  message: async (req, res) => {
    return `Too many requests from ${req.ip}`;
  }
});
```

### statusCode
**Type:** `number`  
**Default:** `429`

HTTP status code sent when rate limit is exceeded.

```typescript
const limiter = rateLimit({
  statusCode: 429 // HTTP 429 Too Many Requests
});
```

### handler
**Type:** `RateLimitExceededEventHandler`

Custom handler function called when rate limit is exceeded.

```typescript { .api }
type RateLimitExceededEventHandler = (
  request: Request,
  response: Response,
  next: NextFunction,
  optionsUsed: Options,
) => void;
```

```typescript
const limiter = rateLimit({
  handler: (req, res, next, options) => {
    res.status(429).json({
      error: "Rate limit exceeded",
      limit: req.rateLimit.limit,
      remaining: req.rateLimit.remaining,
      resetTime: req.rateLimit.resetTime
    });
  }
});
```

## Header Configuration

### legacyHeaders
**Type:** `boolean`  
**Default:** `true`

Enable legacy `X-RateLimit-*` headers for backward compatibility.

```typescript
const limiter = rateLimit({
  legacyHeaders: true // Enables X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset
});
```

### standardHeaders
**Type:** `boolean | DraftHeadersVersion`  
**Default:** `false`

Enable standardized rate limit headers. Options: `false`, `true` (same as `"draft-6"`), `"draft-6"`, `"draft-7"`, `"draft-8"`.

```typescript { .api }
type DraftHeadersVersion = "draft-6" | "draft-7" | "draft-8";
```

```typescript
const limiter = rateLimit({
  standardHeaders: "draft-7", // Enables RateLimit and RateLimit-Policy headers
  legacyHeaders: false
});
```

### identifier
**Type:** `string | ValueDeterminingMiddleware<string>`  
**Default:** Dynamic based on limit and window

Policy identifier used in draft-8 headers.

```typescript
const limiter = rateLimit({
  identifier: "api-access",
  standardHeaders: "draft-8"
});
```

## Request Filtering

### skipFailedRequests
**Type:** `boolean`  
**Default:** `false`

Don't count requests that result in 4xx or 5xx status codes.

```typescript
const limiter = rateLimit({
  skipFailedRequests: true // Failed requests don't count toward limit
});
```

### skipSuccessfulRequests
**Type:** `boolean`  
**Default:** `false`

Don't count requests that result in 2xx or 3xx status codes.

```typescript
const limiter = rateLimit({
  skipSuccessfulRequests: true // Only failed requests count toward limit
});
```

### requestWasSuccessful
**Type:** `ValueDeterminingMiddleware<boolean>`  
**Default:** `(req, res) => res.statusCode < 400`

Custom logic to determine if a request was successful (used with skip options).

```typescript
const limiter = rateLimit({
  skipSuccessfulRequests: true,
  requestWasSuccessful: (req, res) => {
    return res.statusCode >= 200 && res.statusCode < 300; // Only 2xx are successful
  }
});
```

### skip
**Type:** `ValueDeterminingMiddleware<boolean>`  
**Default:** `() => false`

Custom logic to determine if a request should be skipped entirely.

```typescript
const limiter = rateLimit({
  skip: (req, res) => {
    // Skip requests from whitelisted IPs
    return req.ip === "127.0.0.1";
  }
});
```

## Key Generation

### keyGenerator
**Type:** `ValueDeterminingMiddleware<string>`  
**Default:** IP-based with IPv6 subnet grouping

Function to generate unique keys for clients.

```typescript
const limiter = rateLimit({
  keyGenerator: (req, res) => {
    // Use API key if available, otherwise IP
    return req.headers['x-api-key'] || req.ip;
  }
});
```

### ipv6Subnet
**Type:** `number | ValueDeterminingMiddleware<number> | false`  
**Default:** `56`

IPv6 subnet mask for grouping IPv6 addresses. Common values: 32, 48, 56, 60, 64.

```typescript
const limiter = rateLimit({
  ipv6Subnet: 64, // More granular IPv6 grouping
  // or disable IPv6 subnet grouping
  ipv6Subnet: false,
  // or dynamic based on request
  ipv6Subnet: (req, res) => {
    return req.headers['x-strict-limit'] ? 64 : 56;
  }
});
```

## Advanced Configuration

### requestPropertyName
**Type:** `string`  
**Default:** `"rateLimit"`

Property name where rate limit info is stored on the request object.

```typescript
const limiter = rateLimit({
  requestPropertyName: "rateLimitInfo"
});

// Access in middleware
app.use(limiter);
app.use((req, res, next) => {
  console.log(req.rateLimitInfo.remaining);
  next();
});
```

### passOnStoreError
**Type:** `boolean`  
**Default:** `false`

Allow requests through if the store encounters an error.

```typescript
const limiter = rateLimit({
  store: externalStore,
  passOnStoreError: true // Don't fail if external store is unavailable
});
```

### validate
**Type:** `boolean | EnabledValidations`  
**Default:** `true`

Configuration validation settings.

```typescript { .api }
type EnabledValidations = {
  default?: boolean;              // Default validation setting for unlisted validations
  ip?: boolean;                   // Validate IP address format and port presence
  trustProxy?: boolean;           // Check trust proxy configuration
  xForwardedFor?: boolean;        // Validate X-Forwarded-For header usage
  forwardedHeader?: boolean;      // Check for Forwarded header usage
  positiveHits?: boolean;         // Ensure hit counts are positive integers
  unsharedStore?: boolean;        // Prevent store instance sharing between limiters
  singleCount?: boolean;          // Prevent double-counting for same request
  limit?: boolean;                // Validate limit configuration
  draftPolliHeaders?: boolean;    // Check deprecated draft_polli_ratelimit_headers option
  onLimitReached?: boolean;       // Check deprecated onLimitReached option
  headersDraftVersion?: boolean;  // Validate header draft version
  headersResetTime?: boolean;     // Validate reset time for headers
  validationsConfig?: boolean;    // Validate the validation configuration itself
  creationStack?: boolean;        // Check if limiter created inside request handler
  keyGeneratorIpFallback?: boolean; // Check for proper IPv6 handling in custom key generators
  windowMs?: boolean;             // Validate window duration for MemoryStore
};
```

```typescript
const limiter = rateLimit({
  validate: {
    trustProxy: true,    // Validate proxy trust configuration
    xForwardedFor: true, // Validate X-Forwarded-For header usage
    ip: true,           // Validate IP address format
    default: false      // Disable other validations
  }
});
```

## Usage Examples

### API Rate Limiting
```typescript
const apiLimiter = rateLimit({
  windowMs: 15 * 60 * 1000, // 15 minutes
  limit: 1000, // 1000 requests per window
  message: {
    error: "API rate limit exceeded",
    retryAfter: 15 * 60 // seconds
  },
  standardHeaders: "draft-7",
  legacyHeaders: false,
  skipFailedRequests: true
});
```

### Authentication Endpoint Protection
```typescript
const authLimiter = rateLimit({
  windowMs: 15 * 60 * 1000, // 15 minutes
  limit: 5, // 5 attempts per window
  message: "Too many authentication attempts",
  skipSuccessfulRequests: true, // Only failed attempts count
  keyGenerator: (req) => req.body.username || req.ip // Rate limit by username
});
```

### Dynamic Rate Limiting
```typescript
const dynamicLimiter = rateLimit({
  windowMs: 60 * 1000, // 1 minute
  limit: async (req) => {
    const user = await getUserFromToken(req.headers.authorization);
    return user?.plan === 'premium' ? 1000 : 100;
  },
  keyGenerator: async (req) => {
    const user = await getUserFromToken(req.headers.authorization);
    return user?.id || req.ip;
  }
});
```

## Deprecated Options

The following options are deprecated but still supported for backward compatibility:

### headers (DEPRECATED)
**Type:** `boolean`  
**Default:** `true`  
**Replacement:** Use `legacyHeaders` instead

```typescript
// DEPRECATED - but still works
const limiter = rateLimit({
  headers: false
});

// RECOMMENDED
const limiter = rateLimit({
  legacyHeaders: false
});
```

### max (DEPRECATED)
**Type:** `number | ValueDeterminingMiddleware<number>`  
**Default:** `5`  
**Replacement:** Use `limit` instead

```typescript
// DEPRECATED - but still works
const limiter = rateLimit({
  max: 100
});

// RECOMMENDED
const limiter = rateLimit({
  limit: 100
});
```

These deprecated options will be removed in a future major version. Update your code to use the recommended alternatives.