Rate limiting by key

Extension for applying the protection: x-42c-request-limiter_0.1

You apply protections to your API as strategies by using the x-42c security extensions, either locally to specific paths, operations, responses, or HTTP status codes, or alternatively to all incoming requests or outgoing responses. For more details, see Protections and security extensions.

Description

This protection limits how many requests API Firewall accepts in a given time window based on counters. You specify the maximum number of requests allowed (hits) over a period of time in seconds (window). If a counter exceeds this limit, the requests are blocked.

The graphic shows a row of grouped colored dots above a right-pointing arrow that denotes time. The first group has three dots close to each other and underneath is a bracket denoting the time window in the request limiter. This group of dots fits neatly inside the bracket, so each of them is green and decorated with a white checkmark to indicate a successfull request that request limiter allowed through. The second group of two dots follows closely after the first group, but falls outside the window of the request limiter. The two dots are red and have a white cross, indicating requests that the request limiter blocked. There is a slightly longer gap before the third group of dots. These dots are again green with white checkmark; the request limiter has reached the timeout and started a new window, so requests are again allowed through.

Unlike rate limiting by IP address, this protection lets you choose what to base the counters on by specifying in the parameter key which element API Firewall should look for in the incoming request. The key could be based on, for example, a value in the API call, a query parameter, an API key, or a specific token. This gives you more flexibility on how to implement rate limiting.

You can define multiple counters on different levels in your API, for example, to specify different rate limits for operation A and operation B. For this, you can use the parameter cache.name to specify separate caches for these two operations. The counter is the same, but it is counted in separate caches.

The request limiter leverages the cache in API Firewall and stores two kinds of counters: basic limitation and burst limitation. Both counters are stored in the same cache, but are separated by the implementation of the protection.

The basic limitation counters have a timeout value corresponding to the window parameter defined for the protection. When the timeout expires, the counter is automatically removed from the cache. If the counter reaches the maximum number of hits allowed within the time window, the protection blocks any further requests and sends back a HTTP 429: Too many requests response.

The burst limitation counters work in the same way, but they limit how many requests are allowed in smaller rapid bursts. This way, you can temporarily allow higher call rate within a shorter period of time. The request limiter first applies the basic limitation as described above, then, the burst limitation if you have enabled it in the protection parameters. For example, this protection could limit the requests to the API to 15 requests per minute (basic limitation) and allow a burst of two requests per second (burst limitation).

If the protection is applied on global level, it throttles the call rate to the whole API. You can also apply it to a specific operation, such as login. For more details, see Local and global protections.

In microservice deployments, API Firewall is deployed separately with each instance of the microservice, so rate limiting is also enforced separately on each instance. Thus, if you have multiple instances of the same microservice, their combined throughput will be different from the rate limits that each of the API Firewall instances imposes.

Direction

The protection applies only to incoming requests, not outgoing responses, and it mitigates, for example, Denial-of Service (DoS) or brute-force attacks.

Parameters

You can configure the following parameters:

Parameter name Description
key Required. What the counter is based on. This parameter tells API Firewall what element (for example, a query parameter, an API key, or a session ID) in the incoming request to look for and, if found, tick the counter onwards. This parameter is common to both basic and burst limitation.
window Required. The time window (in seconds) before the counter times out. This parameter is for the basic limitation.
hits Required. The maximum number of requests allowed within the defined time window. The number of requests allowed is the combination of the hits and window. For example, if hits is set to 15 and window to 60, the request rate is limited to 15 requests in 60 seconds. This parameter is for the basic limitation.
burst.enabled Enables burst limitation so that requests are evened out by a separate burst counter. The number of requests allowed in a burst is the combination of the burst.hits and burst.window, for example, two requests every five seconds. This parameter is optional. The default value is false.
burst.window The time window (in seconds) for the burst. This parameter is optional. The default value is 2.
burst.hits The maximum number of request in the burst window. This parameter is optional. The default value is 5.
cache.name The name of the cache that is used to store the data. You can use this parameter, for example, to concentrate for a specific operation inside a specific cache name. This parameter is common to both basic and burst limitation. This parameter is optional. The default value is default.
cache.type The cache storage mechanism. Currently, only MEMORY is supported. This parameter is common to both basic and burst limitation. This parameter is optional.

Because the API Firewall instance stores all counters in its memory, if the instance is restarted, all values in the cache are lost.

Example

/api/login:
    post:
        x-42c-local-strategy:
            x-42c-strategy:
                protections:
                    - x-42c-request-limiter_0.1:
                        key: req_limiter_login
                        window: 15
                        hits: 10
                        burst.enabled: true
                        burst.window: 2
                        burst.hits: 5
                        
                    # ...