Configuration Options
Complete reference for all hitlimit configuration options.
Basic Options
| Option | Type | Default | Description |
|---|---|---|---|
limit | number | 100 | Maximum requests per window |
window | string | number | '1m' | Time window (e.g., '1m', '1h', '1d') |
key | function | req.ip | Function to extract rate limit key |
store | Store | memoryStore() | Storage backend |
Advanced Options
| Option | Type | Default | Description |
|---|---|---|---|
skip | function | undefined | Skip rate limiting for certain requests |
headers | boolean | true | Include rate limit headers |
statusCode | number | 429 | HTTP status when rate limited |
response | object | function | - | Custom response body |
Ban Options
Automatically ban clients that repeatedly exceed rate limits. After the configured number of violations, the client is blocked for the ban duration without consuming store hits.
| Option | Type | Default | Description |
|---|---|---|---|
ban.threshold | number | - | Number of rate limit violations before triggering a ban |
ban.duration | string | number | - | How long the ban lasts (e.g., '1h', '30m', or milliseconds) |
hitlimit({
limit: 10,
window: '1m',
ban: {
threshold: 5, // Ban after 5 violations
duration: '1h' // Ban lasts 1 hour
}
}) When a client is banned, the response includes X-RateLimit-Ban: true and X-RateLimit-Ban-Expires headers, plus banned: true in the response body.
Group Options
Group multiple clients under a shared rate limit key prefix. Useful for per-API-key limits, per-tenant throttling, or per-organization quotas.
| Option | Type | Default | Description |
|---|---|---|---|
group | string | function | undefined | Static group name or function returning a group ID per request |
// Static group — all keys prefixed with "api:"
hitlimit({ group: 'api', limit: 100, window: '1m' })
// Dynamic group — per API key
hitlimit({
limit: 1000,
window: '1h',
group: (req) => req.headers['x-api-key'] || 'anonymous'
}) Store Configuration
hitlimit supports four storage backends. Memory is the default and fastest option:
| Store | Best For | Throughput |
|---|---|---|
memoryStore() | Single-process, highest performance | 4.08M ops/s |
sqliteStore() | Persistence across restarts | 404K ops/s |
mongoStore() | Teams already using MongoDB | 2.2K ops/s |
redisStore() | Distributed / multi-server deployments | Network-bound |
postgresStore() | Teams already using Postgres | Network-bound |
| Store | Best For | Throughput |
|---|---|---|
memoryStore() | Single-process, highest performance | 5.57M ops/s |
sqliteStore() | Persistence across restarts (bun:sqlite) | 372K ops/s |
redisStore() | Distributed / multi-server deployments | Network-bound |
postgresStore() | Teams already using Postgres | Network-bound |
import { hitlimit, memoryStore } from '@joint-ops/hitlimit'
import { sqliteStore } from '@joint-ops/hitlimit/stores/sqlite'
import { redisStore } from '@joint-ops/hitlimit/stores/redis'
// Memory (default) — no config needed
hitlimit({ limit: 100, window: '1m' })
// SQLite — persistent storage
hitlimit({
limit: 100,
window: '1m',
store: sqliteStore({ path: './limits.db' })
})
// Redis — distributed
hitlimit({
limit: 100,
window: '1m',
store: redisStore({ url: 'redis://localhost:6379' })
}) import { hitlimit, sqliteStore, redisStore } from '@joint-ops/hitlimit-bun'
// Memory (default) — no config needed
hitlimit({ limit: 100, window: '1m' })
// SQLite — persistent storage via bun:sqlite
hitlimit({
limit: 100,
window: '1m',
store: sqliteStore({ path: './limits.db' })
})
// Redis — distributed
hitlimit({
limit: 100,
window: '1m',
store: redisStore({ url: 'redis://localhost:6379' })
}) Full Example
hitlimit({
limit: 100,
window: '1m',
key: (req) => req.headers['x-api-key'] || req.ip,
store: sqliteStore({ path: './limits.db' }),
skip: (req) => req.path === '/health',
headers: true,
statusCode: 429,
response: { error: 'Too many requests' },
ban: { threshold: 5, duration: '1h' },
group: (req) => req.headers['x-api-key'] || 'default'
})