#Rate Limiting Policy
Rate-limiting allows you to set a maximum rate of requests for your API gateway. This is useful to enforce rate limits agreed with your clients and protect your downstream services.
The Zuplo Rate-Limit allows you to limit based on different attributes of the incoming request. For example, you might set a rate limit of 10 requests per second per user, or 20 requests per second for a given IP address.
The Zuplo rate-limiter also allows you to set a custom bucket name by which to effect a rate-limit using a function.
When a client reaches a rate limit - they will receive a 429
response code.
#Configuration
The configuration shows how to configure the policy in the 'policies.json' document.
{ "name": "my-rate-limit-inbound-policy", "policyType": "rate-limit-inbound", "handler": { "export": "RateLimitInboundPolicy", "module": "$import(@zuplo/runtime)", "options": { "rateLimitBy": "ip", "requestsAllowed": 2, "timeWindowMinutes": 1 } } }json
#Policy Configuration
name
<string>
- The name of your policy instance. This is used as a reference in your routes.policyType
<string>
- The identifier of the policy. This is used by the Zuplo UI. Value should berate-limit-inbound
.handler.export
<string>
- The name of the exported type. Value should beRateLimitInboundPolicy
.handler.module
<string>
- The module containing the policy. Value should be$import(@zuplo/runtime)
.handler.options
<object>
- The options for this policy. See Policy Options below.
#Policy Options
The options for this policy are specified below. All properties are optional unless specifically marked as required.
rateLimitBy
(required)<string>
- The identifying element of the request that enforces distinct rate limits. For example, you can limit byuser
,ip
,function
orall
- function allows you to specify a simple function to create a string identifier to create a rate-limit group. Allowed values areuser
,ip
,function
,all
. Defaults to"user"
.requestsAllowed
(required)<integer>
- The max number of requests allowed in the given time window. Defaults to1000
.timeWindowMinutes
(required)<integer>
- The time window in which the requests are rate-limited. The count restarts after each window expires. Defaults to60
.identifier
<object>
- The function that returns dynamic configuration data. Used only withrateLimitBy=function
.export
(required)<string>
- used only with rateLimitBy=function. Specifies the export to load your custom bucket function, e.g.default
,rateLimitIdentifier
. Defaults to"$import(./modules/my-module)"
.module
(required)<string>
- Specifies the module to load your custom bucket function, in the format$import(./modules/my-module)
. Defaults to""
.
headerMode
<string>
- Adds the retry-after header. Allowed values arenone
,retry-after
. Defaults to"retry-after"
.throwOnFailure
<boolean>
- If true, the policy will throw an error in the event there is a problem connecting to the rate limit service. Defaults tofalse
.mode
<string>
- The mode of the policy. If set toasync
, the policy will check if the request is over the rate limit without blocking. This can result in some requests allowed over the rate limit. Allowed values arestrict
,async
. Defaults to"strict"
.
#Using the Policy
Note you can have multiple instances of rate-limiting policies to use in combination. You should apply the longest duration timeWindow first, in order to the shortest duration time window.
#Using a custom function
You can create a rate-limit bucket based on any property of a request using a
custom function that returns a CustomRateLimitDetails
object (which provides
the identifier used by the limiting system).
The CustomRateLimitDetails
object can be used to override the
timeWindowMinutes
& requestsAllowed
options.
This example would create a unique rate-limiting function based on the
customerId
parameter in routes (note it’s important that a policy like this is
applied to a route that has a /:customerId
parameter).
//module - ./modules/rate-limiter.ts import { CustomRateLimitDetails, ZuploRequest, ZuploContext, } from "@zuplo/runtime"; export function rateLimitKey( request: ZuploRequest, context: ZuploContext, policyName: string, ): CustomRateLimitDetails | undefined { context.log.info( `processing customerId '${request.params.customerId}' for rate-limit policy '${policyName}'`, ); if (request.params.customerId === "43567890") { // Override timeWindowMinutes & requestsAllowed return { key: request.params.customerId, requestsAllowed: 100, timeWindowMinutes: 1, }; } }ts
// config - ./config/policies.json "export": "RateLimitInboundPolicy", "module": "$import(@zuplo/runtime)", "options": { "rateLimitBy": "function", "requestsAllowed": 2, "timeWindowMinutes": 1, "identifier": { "module": "$import(./modules/rate-limiter)", "export": "rateLimitKey" } }json
Read more about how policies work