Tiered Rate Limits
Apply different rate limits based on user tiers such as free, pro, and enterprise plans using the built-in tiers and tier options.
How It Works
Define your tier configurations in tiers, then provide a tier resolver function that returns the tier name for each request. hitlimit picks the correct limit and window automatically.
hitlimit({
tiers: {
free: { limit: 100, window: '1h' },
pro: { limit: 1000, window: '1h' },
enterprise: { limit: 10000, window: '1h' }
},
tier: (req) => req.user?.tier || 'free'
}) TierConfig
| Field | Type | Description |
|---|---|---|
limit | number | Maximum requests per window for this tier (required) |
window | string | number | Time window override for this tier. Falls back to the top-level window if omitted. |
Different Windows per Tier
Each tier can have its own window. Free users get a strict hourly limit; pro users get a more generous per-minute limit:
hitlimit({
tiers: {
free: { limit: 60, window: '1h' }, // 60/hour
pro: { limit: 500, window: '1m' }, // 500/minute
},
tier: (req) => req.user?.tier || 'free'
}) Async Tier Resolution
The tier function can return a Promise, useful for database lookups:
hitlimit({
tiers: {
free: { limit: 100, window: '1h' },
pro: { limit: 5000, window: '1h' },
},
tier: async (req) => {
const user = await getUserFromToken(req.headers['authorization'])
return user?.plan || 'free'
}
}) Tiered Limits + Custom Key
Combine tiers with a custom key to rate limit per user ID within each tier:
hitlimit({
tiers: {
free: { limit: 100, window: '1h' },
pro: { limit: 5000, window: '1h' },
},
tier: (req) => req.user?.plan || 'free',
key: (req) => req.user?.id || req.ip
}) Unknown Tier Fallback
If tier returns a name that isn't in tiers, hitlimit falls back to the top-level limit and window. Always define a default tier (e.g. 'free') or set a top-level limit as a safety net:
hitlimit({
limit: 50, // fallback if tier not found
window: '1h',
tiers: {
pro: { limit: 5000 }
},
tier: (req) => req.user?.plan || 'unknown'
})