rateLimit
Source Code | DocumentationRate limits service method calls using rate-limiter-flexible. You provide a pre-configured RateLimiterAbstract instance (Memory, Redis, Mongo, etc.) and the hook consumes points per request.
import { } from 'feathers-utils/hooks';Example
import { rateLimit } from 'feathers-utils/hooks'
import { RateLimiterMemory } from 'rate-limiter-flexible'
const rateLimiter = new RateLimiterMemory({ points: 10, duration: 1 })
app.service('users').hooks({
before: { find: [rateLimit(rateLimiter)] }
})Type declaration
Show Type Declarations
export type RateLimitOptions<H extends HookContext = HookContext> = {
/** Generate the rate-limiting key. Defaults to `context.path`. */
key?: (context: H) => Promisable<string>
/** Number of points to consume per request. Defaults to `1`. */
points?: (context: H) => Promisable<number>
}
/**
* Rate limits service method calls using `rate-limiter-flexible`.
* You provide a pre-configured `RateLimiterAbstract` instance
* (Memory, Redis, Mongo, etc.) and the hook consumes points per request.
*
* @example
* ```ts
*
*
*
* const rateLimiter = new RateLimiterMemory({ points: 10, duration: 1 })
*
* app.service('users').hooks({
* before: { find: [rateLimit(rateLimiter)] }
* })
* ```
*
* @see https://utils.feathersjs.com/hooks/rate-limit.html
*/
export declare const rateLimit: <H extends HookContext = HookContext>(
rateLimiter: RateLimiterAbstract,
options?: RateLimitOptions<H>,
) => (context: H, next?: NextFunction) => Promise<any>| Argument | Type | Description |
|---|---|---|
| rateLimiter | RateLimiterAbstract | |
| options | RateLimitOptions<H> |
| type | methods | multi |
|---|---|---|
| before, around | find, get, create, update, patch, remove | yes |
The rateLimit hook limits how many times a service method can be called within a time window using rate-limiter-flexible. You provide a pre-configured rate limiter instance — the hook calls consume() on each request and throws a TooManyRequests error when the limit is exceeded.
Any rate limiter backend supported by rate-limiter-flexible can be used (Memory, Redis, Mongo, Postgres, etc.).
Options
| Option | Type | Description |
|---|---|---|
key | (context) => string | Generate the rate-limiting key. Defaults to context.path. |
points | (context) => number | Number of points to consume per request. Defaults to 1. |
The RateLimiterRes is stored on context.params.rateLimit on both success and failure, so downstream hooks or services can inspect remainingPoints, consumedPoints, msBeforeNext, etc.
Examples
Basic Usage
import { rateLimit } from 'feathers-utils/hooks'
import { RateLimiterMemory } from 'rate-limiter-flexible'
const rateLimiter = new RateLimiterMemory({
points: 10, // 10 requests
duration: 1, // per 1 second
})
app.service('users').hooks({
before: {
find: [rateLimit(rateLimiter)],
},
})Rate Limit per User
Use the key option to rate limit per authenticated user instead of per service path:
const rateLimiter = new RateLimiterMemory({ points: 100, duration: 60 })
app.service('messages').hooks({
before: {
create: [
rateLimit(rateLimiter, {
key: (context) => `${context.path}:${context.params.user?.id}`,
}),
],
},
})Custom Points per Request
Use the points option to consume more points for expensive operations:
app.service('reports').hooks({
before: {
find: [
rateLimit(rateLimiter, {
points: (context) => context.params.query?.$limit > 100 ? 5 : 1,
}),
],
},
})Redis Backend
import { RateLimiterRedis } from 'rate-limiter-flexible'
import Redis from 'ioredis'
const redisClient = new Redis()
const rateLimiter = new RateLimiterRedis({
storeClient: redisClient,
points: 100,
duration: 60,
keyPrefix: 'rl',
})
app.service('users').hooks({
before: {
find: [rateLimit(rateLimiter)],
},
})Bypass with iff
Use iff to skip rate limiting for internal (server-side) calls:
import { rateLimit, iff } from 'feathers-utils/hooks'
import { isProvider } from 'feathers-utils/predicates'
app.service('users').hooks({
before: {
find: [
iff(isProvider('rest', 'socketio', 'external'), rateLimit(rateLimiter)),
],
},
})Bypass with skippable
Use skippable to allow specific callers to opt out of rate limiting:
import { rateLimit, skippable } from 'feathers-utils/hooks'
app.service('users').hooks({
before: {
find: [skippable(rateLimit(rateLimiter))],
},
})
// Skip rate limiting for this call
app.service('users').find({ skipHooks: ['rateLimit'] })