Skip to main content

Plugin - Rate Limit

This plugin can be used to stop your server from being overloaded with too many requests in a brief period.

Your (optional)ratelimit mapping endpointAdditional Rate LimitsHTTP requestheadersUserYour systemLoad balancerDestination endpointGateHTTP requestHTTP request?

Configuring Gate

GATE_PLUGINS_<PLUGIN NUMBER>_TYPE=ratelimit
GATE_PLUGINS_<PLUGIN NUMBER>_PARAMETERS_LIMITS_<LIMIT NUMBER>_KEY=<Limit Key>
GATE_PLUGINS_<PLUGIN NUMBER>_PARAMETERS_LIMITS_<LIMIT NUMBER>_COMMENT=<Limit Comment>
GATE_PLUGINS_<PLUGIN NUMBER>_PARAMETERS_LIMITS_<LIMIT NUMBER>_INTERVAL=<Limit Interval>
GATE_PLUGINS_<PLUGIN NUMBER>_PARAMETERS_LIMITS_<LIMIT NUMBER>_BURST=<Limit Burst>
GATE_PLUGINS_<PLUGIN NUMBER>_PARAMETERS_LIMITS_<LIMIT NUMBER>_WINDOW=<Limit Window>
GATE_PLUGINS_<PLUGIN NUMBER>_PARAMETERS_LIMITS_<LIMIT NUMBER>_MAX_THROTTLE=<Limit Max-throttle>
GATE_PLUGINS_<PLUGIN NUMBER>_PARAMETERS_LIMITS_<LIMIT NUMBER>_REQUEST_FIELD=<Limit Request Field>
GATE_PLUGINS_<PLUGIN NUMBER>_PARAMETERS_ENABLED_HEADERS_RETRY_AFTER=<Header Retry-After>
GATE_PLUGINS_<PLUGIN NUMBER>_PARAMETERS_ENABLED_HEADERS_RATELIMIT_LIMIT=<Header Ratelimit-Limit>
GATE_PLUGINS_<PLUGIN NUMBER>_PARAMETERS_ENABLED_HEADERS_RATELIMIT_QUOTA_POLICY=<Header Quota-Policy>
GATE_PLUGINS_<PLUGIN NUMBER>_PARAMETERS_ENABLED_HEADERS_RATELIMIT_QUOTA_KEY=<Header Quota Key>
GATE_PLUGINS_<PLUGIN NUMBER>_PARAMETERS_ENABLED_HEADERS_RATELIMIT_QUOTA_COMMENT=<Header Quota Comment>
GATE_PLUGINS_<PLUGIN NUMBER>_PARAMETERS_ENABLED_HEADERS_RATELIMIT_REMAINING=<Header Ratelimit-Remaining>
GATE_PLUGINS_<PLUGIN NUMBER>_PARAMETERS_ENABLED_HEADERS_RATELIMIT_RESET=<Header Ratelimit-Reset>
GATE_PLUGINS_<PLUGIN NUMBER>_PARAMETERS_LIMITER_TYPE=<Limiter Type>
GATE_PLUGINS_<PLUGIN NUMBER>_PARAMETERS_LIMITER_ADDRESS=<Limiter Address>
GATE_PLUGINS_<PLUGIN NUMBER>_PARAMETERS_LIMITER_KEY_PREFIX=<Limiter Key Prefix>
GATE_PLUGINS_<PLUGIN NUMBER>_PARAMETERS_HEADER_WITH_TOKEN=<Header with token>
GATE_PLUGINS_<PLUGIN NUMBER>_PARAMETERS_COOKIE_WITH_TOKEN=<Cookie with token>
GATE_PLUGINS_<PLUGIN NUMBER>_PARAMETERS_MONITORING_MODE=<Monitoring Mode>
GATE_PLUGINS_<PLUGIN NUMBER>_PARAMETERS_MAP_LIMITS_ENDPOINT=<Map Limits Endpoint>

In Environment variables configuration, <PLUGIN NUMBER> defines plugin execution order, while <LIMIT NUMBER> is used to group multiple ratelimits methods with their options (the order is irrelevant).

where:

  • <Limit Key> is the internal identifier of each rate limiter.

  • <Limit Comment> is an optional description string returned in the Ratelimit-Limit header if <Header Quota Comment> is enabled.

  • <Limit Interval> is the minimum interval between requests (ignoring bursts). e.g., 1s. You must specify either <Limit Interval> or <Limit Burst> (interval = window / burst)

  • <Limit Burst> is the maximum number of requests that can in a time window. e.g., 10. You must specify either <Limit Interval> or <Limit Burst> (burst = window / interval)

  • <Limit Window> is the amount of time considered for rate limiting. e.g., 1h, 5m, 30s

  • <Limit Max-throttle> is the optional maximum amount of time to wait if the rate limit is currently exceeded. e.g., 5s.

    Throttling works well if you have very few clients making lots of sequential requests, but is better avoided if you have many concurrent clients.

  • <Limit Request Field> is an optional JsonPath used to extract a complement to the limit key from the request's JSON Representation.

    If the path matches the request the value is appended to the limit key, otherwise the current limit is ignored.

    e.g., $.request.http.headers['X-User-Id'][0], $.request.http.cookies['my-cookie'], $.request.parsed_token.payload.sub.

  • <Limiter Type> is the rate limiter implementation to use, and can be:

    • memory (default): Is ideal for single-instance deployments
    • redis_lua: Uses a rate-limiting lua script running in your Redis server. It requires no additional setup and provides good performance.
    • redis_module: Uses a rate-limiting native module that needs to be loaded in the redis server. This provides the best performance, but requires additional setup on the Redis server (which may be impossible in hosted platforms)
    • redis_unlocked: Executes the rate-limiting logic in Gate while persisting state in Redis. It is non-atomic and may sometimes exceed the desired rate-limit. Only use this if you need to keep your Redis server free of custom code.
  • <Limiter Address> is the address of the Redis server (if using a Redis-based limiter type). e.g., redis:6379

  • <Limiter Key Prefix> is a prefix to be added to all keys on the Redis server (if using a Redis-based limiter type) in order to avoid namespace clashes. Defaults to gate-ratelimit

  • <Header Retry-After> is a boolean indicating if a Retry-After header should be added to the response when a request is rejected by the ratelimiter (ignored if <Monitoring Mode> is enabled)

  • <Header Ratelimit-Limit> is a boolean indicating if a Ratelimit-Limit header should be added to the response.

  • <Header Quota-Policy> is a boolean indicating if details of the Quota-Policy should be included in the Ratelimit-Limit response header (depends on <Header Ratelimit-Limit>)

  • <Header Quota Key> is a boolean indicating if the ratelimit key should be added to the Quota-Policy information in the Ratelimit-Limit response header (depends on <Header Quota-Policy>). This is a Gate-specific extension and should only be used for development.

  • <Header Quota Comment> is a boolean indicating if the ratelimit comment should be added to the Quota-Policy information in the Ratelimit-Limit response header (depends on <Header Quota-Policy>).

  • <Header Ratelimit-Remaining> is a boolean indicating if a Ratelimit-Remaining header should be added to the response.

  • <Header Ratelimit-Reset> is a boolean indicating if a Ratelimit-Reset header should be added to the response.

  • <Header with token> is the request header containing a JWT token, if any. This option and <Cookie with token> are mutually exclusive.

  • <Cookie with token> is the request cookie containing a JWT token, if any. This option and <Header with token> are mutually exclusive.

  • <Monitoring Mode> is a boolean indicating if the ratelimit plugin should stop a rejected request immediately (false), or if the request handler should be responsible for handling the result of the ratelimit check (true).

  • <Map Limits Endpoint> is an optional HTTP URL which will be used to extract additional rate limits from the request headers.

To learn more about configuring Gate, please visit the configuration page and plugins section.

info

The order of the plugins in the configuration determines their execution order.

Rate-limit differentiation

It is often necessary to apply independent limits per user (or groups, or any other criteria). To achieve that the ratelimit plugin allows using the <Limit Request Field> option to specify a JsonPath which will be used to retrieve the additional information necessary for differentiation from the request.

The additional value is then appended to the limit key in the config, producing an independent rate limit.

The following is an example of input object Gate makes available to JsonPath evaluation:

{
"version": {
"gate": "v1.1"
},
"request": {
"http": {
"headers": {
"Accept": [
"application/json, text/plain, */*"
],
"Accept-Encoding": [
"gzip, compress, deflate, br"
],
"Authorization": [
"Bearer eyJhb..."
],
"Cookie": [
"foo=bar"
]
"User-Agent": [
"axios/1.3.4"
]
},
"cookies": {
"foo": "bar"
}
"host": "example.com",
"method": "GET",
"path": "/some/path",
"protocol": "HTTP/1.1",
"query": "option=value",
"scheme": "https",
"url": "https://example.com/some/path?option=value"
},
"parsed_path": [
"some",
"path"
],
"parsed_query": {
"option": [
"value"
]
},
"parsed_token": {
"header": {
"alg": "RS256",
"kid": "pYsNGA"
},
"payload": {
...
},
"signature": "JvVt..."
},
"time": "2023-04-09T18:38:41.117405838Z",
"token": "eyJh..."
}
}

You can use the <Header with token> or <Cookie with token> settings to parse a JWT token. If neither <Header with token> nor <Cookie with token> are set, the plugin attempts to get a bearer token from the Authorization header, and strips the Bearer prefix from it. Keep in mind that this plugin does not verify JWT signatures, you should use the JWT verification plugin for that.

A few typical examples for the <Limit Request Field> JsonPath selector:

  • $.request.http.headers['X-User-Id'][0]: Retrieves user id from a custom header
  • $.request.http.cookies['my-cookie']: Retrieves user id from a cookie
  • "$.request.parsed_token.payload.sub": Retrieves user id from the sub claim in a JWT token.
caution

If the <Limit Request Field> configuration is provided but doesn't match the current request, the ratelimit is not enforced.

For more complex differentiation use cases, you can use custom mapping endpoints.

Map Limits Endpoint

If specified, for every incoming request the rate limiter plugin will make a GET request to specified endpoint.

All headers of the original request are forwarded to the mapping endpoint. Two additional headers are included in the request:

  • SlashID-Target-Method
  • SlashID-Target-Location

These carry the method and location of the original request, respectively.

This endpoint should use custom logic to extract a list of additional rate limits to be checked (e.g. it may use custom code to extract an user ID from a session cookie).

The response must be HTTP 200 (OK) and must be JSON-formatted. E.g.,:

{
"limits": [
{
"key": "users/john.smith",
"comment": "username",
"interval": 0.1, // In seconds. Use either interval or burst
//"burst": 10, // Use either interval or burst
"window": 1, // In seconds
"max_throttle": 5, // In seconds
}
]
}

Monitoring Mode

By default, this plugin will automatically reject excessive requests with HTTP error 429 (Too Many Requests), and will automatically sleep before completing the request if throttling is necessary.

However it is possible to let the request go through by enabling monitoring mode. It is then up to your request handler to decide how to proceed when the ratelimit is exceeded or requires throttling.

The following request headers are always added by the ratelimiter:

  • X-Gate-Ratelimit-MonitoringMode: boolean indicating if monitoring mode is enabled.
  • X-Gate-Ratelimit-Allowed: boolean indicating if the request was allowed by the rate limiter. If monitoring mode is enabled your code should handle rejections.
  • X-Gate-Ratelimit-Remaining: Number of additional requests that can be made right away without exceeding the rate limit.
  • X-Gate-Ratelimit-ReadyAfter: Amount of time to wait before the rate limiter allows another request.
  • X-Gate-Ratelimit-ResetAfter: Amount of time until the rate limiter resets to its full capacity (if no more requests are made)
  • X-Gate-Ratelimit-ThrottleWait: Amount of time that the request should be delayed to avoid exceeding the rate limit. If monitoring mode is enabled your code should sleep the specified amount of time.

Disabling plugin for specific URLs

You can enable or disable this plugin for specific URLs by using the enabled option in the URLs configuration.

GATE_URLS_0_PATTERN=svc-example.com/*
GATE_URLS_0_TARGET=http://example:8080

GATE_URLS_1_PATTERN=svc-another-example.com/
GATE_URLS_1_TARGET=https://another-example:8080