Skip to main content
Advanced rate limiting rules allow you to control the number of specific requests accepted by your domain within a defined time window. This functionality is part of WAAP advanced rules. Advanced rate limiting rules are fully defined and managed through the Gcore WAAP API. They can also be viewed, enabled, disabled, and deleted through the Gcore Customer Portal. Rate limiting conditions are evaluated as part of a rule’s condition logic and can be combined with other request attributes to precisely control when an action is triggered. In addition to request thresholds and time intervals, advanced rate limiting conditions support multiple parameters, including request origin, URL patterns, request methods, response status codes, aggregation scope, and tags, enabling flexible and targeted traffic control.

Rate limiting method

Use the request.limit_rate method to implement rate limiting: limit_rate fixed method signature
request.limit_rate(
    requests = <int>,
    interval = <int>,
    url = <string>,
	ip_list = [<string>, ...],
	method_list = [<string>, ...],
    status_list = [<int>, ...],
    content_type = <string>,
    scope = <string>,
    tag = <string>
)
Specify the tag parameter when configuring tag-based rate limiting rules. The method returns true , and the enclosing rule condition is satisfied when the request count (4), under the granularity (8), exceeds the configured threshold within the specified time window (3), using the configured filters (1, 2, 5, 6, 7, 9).
#Parameter nameRequiredDescription
1ip_listFalseList of IP addresses that the rule applies to.
If there are no IPs in the list, counting will be done for all IPs.
2urlTrueA regex pattern used to match the request’s URI (URL + query_params).
3intervalTrueThe time limit, in seconds, within which we only allow n number of requests to URI matching the pattern.
4requestsTrueThe maximum number of requests accepted within the given period before an action is taken (minimum value is 21 requests).
5method_listFalseList of method types the request aggregation will be applied to.
6status_listFalseList of status codes the request aggregation will be applied to.
7content_typeFalseRegex pattern to match request content_type against.
8scope (granularity)False
If the granularity isn’t set to cluster, the default aggregation will be set to cluster.
When protecting the origin, you can configure rate limit rules that apply to either IPs or all requests that come through the cluster.
- If you set it to IP, once the IP exceeds the threshold, the rule is triggered. This helps against individual attackers
- If you set it to cluster, once the total requests (from any IP) exceed the threshold, the rule is triggered. This helps protect the origin from getting too many requests.
9tagFalseAggregation of tagged (user-defined tags) requests will be applied for each IP.

Implementation

Advanced rules via API

curl --request POST \
--url https://api.gcore.com/waap/v1/domains/{domain_id}/advanced-rules \
--header 'accept: application/json' \
--header 'content-type: application/json' \
--data '{
  "action": {
    "block": {
      "status_code": 403
    }
  },
  "phase": "access",
  "name": "Block Scrappers",
  "description": "Block IPs that hit more than 200 requests per 5 seconds for any `events` paths",
  "enabled": false,
  "source": "request.limit_rate(url='.*events', interval=5, requests=200, scope='ip') and not ('mb-web-ui' in request.headers['Cookie'] or 'mb-mobile-ios' in request.headers['Cookie'] or 'mobile-android' in request.headers['Cookie'] or 'mb-mobile-android' in request.headers['Cookie'] or 'session-token' in request.headers['Cookie']) and not request.headers['session']"
}'

Best practices

Block IPs that exceed request limit for any URL

Each request will be counted individually for each IP. For example, if the IP address 1.2.3.4 sends more than 200 requests within a 5-second timeframe, it will be blocked. Another IP address, such as 1.2.3.5, will only be blocked if it exceeds the allowed threshold of 200 requests in the same time interval.
curl --request POST \
--url https://api.gcore.com/waap/v1/domains/{domain_id}/advanced-rules \
--header 'accept: application/json' \
--header 'content-type: application/json' \
--data '{
  "action": {
    "block": {
      "status_code": 403
    }
  },
  "phase": "access",
  "name": "Limit Certain IPs",
  "description": "Limit Certain IPs",
  "enabled": false,
  "source": "request.limit_rate(ip_list=['1.2.3.4','1.2.3.5'], url='.*events', interval=5, requests=200, scope='ip')"
}'

Embed additional conditions

curl --request POST \
--url https://api.gcore.com/waap/v1/domains/{domain_id}/advanced-rules \
--header 'accept: application/json' \
--header 'content-type: application/json' \
--data '{
  "action": {
    "block": {
      "status_code": 403
    }
  },
  "phase": "access",
  "name": "Embedding additional condition to rate limit feature",
  "description": "Embedding additional condition to rate limit feature",
  "enabled": false,
  "source": "request.headers['User-Agent'] == 'Firefox' and request.limit_rate(ip_list=['1.2.3.4','1.2.3.5'], url='.*events', interval=5, requests=200, scope='ip')"
}'

Rate limit complex URL regex

curl --request POST \
--url https://api.gcore.com/waap/v1/domains/{domain_id}/advanced-rules \
--header 'accept: application/json' \
--header 'content-type: application/json' \
--data '{
  "action": {
    "block": {
      "status_code": 403
    }
  },
  "phase": "access",
  "name": "Rate limit complexed URL regex",
  "description": "Rate limit complexed URL regex",
  "enabled": false,
  "source": "request.limit_rate(url='.*(?<!aif|aiff|au|avi|bin|bmp|cab|carb|cct|cdf|class|css|doc|dor|dtd|exe|flv|gcf|gff|gif|grv hdmt hqx|ico|ini|jpeg|jpg|js|mov|mp3|nc|pct|pdf|png|ppc|pws|svg|swa|swf|txt|vbs|w32|wav|wbmp|wml|wmlc|wmls|wmlsc|xsd|zip|webp|jxr|hdp|wdp|webm|ogv|mp4|tif|woff|wot|woff|woff)$', interval=120, requests=20, scope='ip')"
}'

Embed IP range to the condition

curl --request POST \
--url https://api.gcore.com/waap/v1/domains/{domain_id}/advanced-rules \
--header 'accept: application/json' \
--header 'content-type: application/json' \
--data '{
  "action": {
    "block": {
      "status_code": 403
    }
  },
  "phase": "access",
  "name": "Embedding IP range to the condition",
  "description": "Embedding IP range to the condition",
  "enabled": false,
  "source": "request.ip_in_range('10.0.0.0', '10.255.255.255') and request.limit_rate(url='.*[.]jpg', interval=120, requests=20, scope='ip')"
}'

Cluster (PoP) granularity

Rate limit all GET or HEAD redirected (302) requests with specific content type:
curl --request POST \
--url https://api.gcore.com/waap/v1/domains/{domain_id}/advanced-rules \
--header 'accept: application/json' \
--header 'content-type: application/json' \
--data '{
  "action": {
    "block": {
      "status_code": 403
    }
  },
  "phase": "access",
  "name": "RL GET or HEAD redirected requests with specific content type on Cluster granularity",
  "description": "Rate limit all GET or HEAD redirected requests with specific content type on Cluster granularity",
  "enabled": false,
  "source": "request.limit_rate(url='.*url', interval=120, requests=20, method_list=['GET','HEAD'], status_list=[302], content_type='text/html; charset=utf-8', scope='cluster')"
}'

Rate limit by tag filter

This functionality allows embedding user-defined tags into the rate limit condition so only tagged IPs requests will be aggregated into the rate limit mechanism. Note that my tag is a user-defined tag that should be defined in a separate rule.
curl --request POST \
--url https://api.gcore.com/waap/v1/domains/{domain_id}/advanced-rules \
--header 'accept: application/json' \
--header 'content-type: application/json' \
--data '{
  "action": {
    "block": {
      "status_code": 403
    }
  },
  "phase": "access",
  "name": "Embedding tag to the condition",
  "enabled": false,
  "source": "request.limit_rate(tag='my tag', ip_list=['2.3.4.5'], url='/my_url/.*', interval=10, requests=120, scope='ip')"
}'

Clarification: rate limit aggregation and rule triggering

Rate limit aggregation is defined exclusively by the parameters of the request.limit_rate(...) condition, such as the aggregation scope, IP list, or tags. When request.limit_rate(...) is combined with additional conditions in the same rule, those additional conditions control when the rule action is applied, not how requests are aggregated. For example, if a rate limit condition is configured without an IP list and combined with a condition such as request.ip == '1.2.3.4', request aggregation will still occur according to the rate limit definition. However, the rule action will only be triggered when the full rule condition evaluates to true, in this case, only for requests originating from 1.2.3.4. This distinction is important when combining rate limiting with other conditions to help ensure the rule behaves as expected.