limit-count-advanced
The limit-count-advanced plugin uses a fixed or sliding window algorithm to limit the rate of requests by the number of requests within a given time interval. Requests exceeding the configured quota will be rejected.
Specifically:
- Fixed window algorithm tracks requests in non-overlapping time intervals. If the request count exceeds the quota in any interval, excess requests are immediately rejected until the next time window begins.
- Sliding window algorithm tracks requests in overlapping intervals, smoothing out the rate limit by counting recent requests within the last configured time period, regardless of when the interval began. This method reduces traffic spikes and is more effective at evenly distributing requests over time.
Additionally, you may also see the following rate limiting response headers, the name of which can be customized using plugin metadata:
X-RateLimit-Limit: the total quotaX-RateLimit-Remaining: the remaining quotaX-RateLimit-Reset: number of seconds left for the counter to reset
Occasionally, you might observe a small negative value for the X-RateLimit-Remaining. This is acceptable as the sliding window algorithm is an approximation.
Local vs Redis Rate Limiting
The limit-count-advanced plugin supports two modes of rate limiting:
- Local rate limiting: Limits are enforced independently on each gateway instance. Each instance maintains its own counters, so the effective limit is roughly (limit × number of instances) when traffic is spread across instances. This is the default when no
policyis set or whenpolicyislocal. - Redis-based rate limiting: Limits are shared across all gateway instances through Redis. All instances share the same quota, so the configured limit applies to all gateway instances.
Examples
The plugin supports sliding window algorithm in addition to the limit-count plugin features. Please refer to limit-count plugin for fixed window examples, which can also be configured in limit-count-advanced.
The examples below demonstrate how you can use limit-count-advanced to rate limit using sliding window algorithm.
Rate Limit with Local Counters
The following example demonstrates how you can configure limit-count-advanced to use the sliding window algorithm for rate limiting on a route, using the counter in the gateway. Note that each gateway instance has its own counter and independent quota. If you have multiple gateway instances that need to share the same quota, please see share quota among gateways with a Redis server.
Create a route with limit-count-advanced plugin that allows for a quota of 5 within a 10-second sliding window per remote address:
- Admin API
- ADC
- Ingress Controller
curl "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d '{
"id": "limit-count-sliding-route",
"uri": "/get",
"plugins": {
"limit-count-advanced": {
"policy": "local",
"count": 5,
"time_window": 10,
"rejected_code": 429,
"key_type": "var",
"key": "remote_addr",
"window_type": "sliding"
}
},
"upstream": {
"type": "roundrobin",
"nodes": {
"httpbin.org:80": 1
}
}
}'
services:
- name: httpbin
routes:
- uris:
- /get
name: limit-count-sliding-route
plugins:
limit-count-advanced:
policy: local
count: 5
time_window: 10
rejected_code: 429
key_type: var
key: remote_addr
window_type: sliding
upstream:
type: roundrobin
nodes:
- host: httpbin.org
port: 80
weight: 1
Synchronize the configuration to the gateway:
adc sync -f adc.yaml
- Gateway API
- APISIX CRD
apiVersion: v1
kind: Service
metadata:
namespace: aic
name: httpbin-external-domain
spec:
type: ExternalName
externalName: httpbin.org
---
apiVersion: apisix.apache.org/v1alpha1
kind: PluginConfig
metadata:
namespace: aic
name: limit-count-advanced-plugin-config
spec:
plugins:
- name: limit-count-advanced
config:
policy: local
count: 5
time_window: 10
rejected_code: 429
key_type: var
key: remote_addr
window_type: sliding
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
namespace: aic
name: limit-count-sliding-route
spec:
parentRefs:
- name: apisix
rules:
- matches:
- path:
type: Exact
value: /get
filters:
- type: ExtensionRef
extensionRef:
group: apisix.apache.org
kind: PluginConfig
name: limit-count-advanced-plugin-config
backendRefs:
- name: httpbin-external-domain
port: 80
apiVersion: apisix.apache.org/v2
kind: ApisixUpstream
metadata:
namespace: aic
name: httpbin-external-domain
spec:
ingressClassName: apisix
externalNodes:
- type: Domain
name: httpbin.org
---
apiVersion: apisix.apache.org/v2
kind: ApisixRoute
metadata:
namespace: aic
name: limit-count-sliding-route
spec:
ingressClassName: apisix
http:
- name: limit-count-sliding-route
match:
paths:
- /get
methods:
- GET
upstreams:
- name: httpbin-external-domain
plugins:
- name: limit-count-advanced
config:
policy: local
count: 5
time_window: 10
rejected_code: 429
key_type: var
key: remote_addr
window_type: sliding
Apply the configuration:
kubectl apply -f limit-count-advanced-ic.yaml
Generate 7 requests to the route every other second:
for i in $(seq 7); do
(curl -I "http://127.0.0.1:9080/get" &)
sleep 1
done
You should receive HTTP/1.1 200 OK responses for most requests, with the remainder being HTTP 429 Too Many Requests responses. The specific number rejected depends on when the first request is sent.
Share Quota Among Gateways with a Redis Server
The following example demonstrates the rate limiting of requests across multiple gateway nodes with a Redis server using the sliding window algorithm, such that different gateway nodes share the same rate limiting quota.
Create a route with the following configurations in the gateway group:
- Admin API
- ADC
- Ingress Controller
curl "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d '{
"id": "limit-count-sliding-route",
"uri": "/get",
"plugins": {
"limit-count-advanced": {
"count": 1,
"time_window": 30,
"rejected_code": 429,
"key": "remote_addr",
"policy": "redis",
"redis_host": "192.168.xxx.xxx",
"redis_port": 6379,
"redis_password": "p@ssw0rd",
"redis_database": 1,
"window_type": "sliding",
"sync_interval": 0.2
}
},
"upstream": {
"type": "roundrobin",
"nodes": {
"httpbin.org:80": 1
}
}
}'
services:
- name: httpbin
routes:
- uris:
- /get
name: limit-count-sliding-route
plugins:
limit-count-advanced:
count: 1
time_window: 30
rejected_code: 429
key: remote_addr
policy: redis
redis_host: "192.168.xxx.xxx"
redis_port: 6379
redis_password: "p@ssw0rd"
redis_database: 1
window_type: sliding
sync_interval: 0.2
upstream:
type: roundrobin
nodes:
- host: httpbin.org
port: 80
weight: 1
Synchronize the configuration to the gateway:
adc sync -f adc.yaml
- Gateway API
- APISIX CRD
apiVersion: v1
kind: Service
metadata:
namespace: aic
name: httpbin-external-domain
spec:
type: ExternalName
externalName: httpbin.org
---
apiVersion: apisix.apache.org/v1alpha1
kind: PluginConfig
metadata:
namespace: aic
name: limit-count-advanced-plugin-config
spec:
plugins:
- name: limit-count-advanced
config:
count: 1
time_window: 30
rejected_code: 429
key: remote_addr
policy: redis
redis_host: "redis-service.aic.svc"
redis_port: 6379
redis_password: "p@ssw0rd"
redis_database: 1
window_type: sliding
sync_interval: 0.2
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
namespace: aic
name: limit-count-sliding-route
spec:
parentRefs:
- name: apisix
rules:
- matches:
- path:
type: Exact
value: /get
filters:
- type: ExtensionRef
extensionRef:
group: apisix.apache.org
kind: PluginConfig
name: limit-count-advanced-plugin-config
backendRefs:
- name: httpbin-external-domain
port: 80
apiVersion: apisix.apache.org/v2
kind: ApisixUpstream
metadata:
namespace: aic
name: httpbin-external-domain
spec:
ingressClassName: apisix
externalNodes:
- type: Domain
name: httpbin.org
---
apiVersion: apisix.apache.org/v2
kind: ApisixRoute
metadata:
namespace: aic
name: limit-count-sliding-route
spec:
ingressClassName: apisix
http:
- name: limit-count-sliding-route
match:
paths:
- /get
methods:
- GET
upstreams:
- name: httpbin-external-domain
plugins:
- name: limit-count-advanced
config:
count: 1
time_window: 30
rejected_code: 429
key: remote_addr
policy: redis
redis_host: "redis-service.aic.svc"
redis_port: 6379
redis_password: "p@ssw0rd"
redis_database: 1
window_type: sliding
sync_interval: 0.2
Apply the configuration:
kubectl apply -f limit-count-advanced-ic.yaml
❶ policy: Set to redis to use a Redis instance for rate limiting.
❷ redis_host: Set to Redis instance IP address.
❸ redis_port: Set to Redis instance listening port.
❹ redis_password: Set to the password of the Redis instance, if any.
❺ redis_database: Set to the database number in the Redis instance.
❻ window_type: Set the window type to sliding window.
❼ sync_interval: Set the synchronization interval (optional).
Generate 7 requests to the route every other second:
for i in $(seq 7); do
(curl -I "http://127.0.0.1:9080/get" &)
sleep 1
done
You should receive HTTP/1.1 200 OK responses for most requests, with the remainder being HTTP 429 Too Many Requests responses. The specific number rejected depends on when the first request is sent. This verifies routes configured in different gateway nodes share the same quota.
Share Quota Among Gateway Nodes with a Redis Cluster
The following example demonstrates how you can configure limit-count-advanced to use the sliding window algorithm and apply the same quota across multiple gateway nodes, such that different gateway nodes share the same rate limiting quota.
Ensure that your Redis instances are running in cluster mode. A minimum of two nodes are required for the limit-count-advanced plugin configurations.
Create a route with the following configurations in the gateway group:
- Admin API
- ADC
- Ingress Controller
curl "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d '{
"id": "limit-count-route",
"uri": "/get",
"plugins": {
"limit-count-advanced": {
"count": 1,
"time_window": 30,
"rejected_code": 429,
"key": "remote_addr",
"policy": "redis-cluster",
"redis_cluster_nodes": [
"192.168.xxx.xxx:6379",
"192.168.xxx.xxx:16379"
],
"redis_password": "p@ssw0rd",
"redis_cluster_name": "redis-cluster",
"redis_cluster_ssl": true,
"window_type": "sliding",
"sync_interval": 0.2
}
},
"upstream": {
"type": "roundrobin",
"nodes": {
"httpbin.org:80": 1
}
}
}'
services:
- name: httpbin
routes:
- uris:
- /get
name: limit-count-route
plugins:
limit-count-advanced:
count: 1
time_window: 30
rejected_code: 429
key: remote_addr
policy: redis-cluster
redis_cluster_nodes:
- "192.168.xxx.xxx:6379"
- "192.168.xxx.xxx:16379"
redis_password: "p@ssw0rd"
redis_cluster_name: "redis-cluster"
redis_cluster_ssl: true
window_type: sliding
sync_interval: 0.2
upstream:
type: roundrobin
nodes:
- host: httpbin.org
port: 80
weight: 1
Synchronize the configuration to the gateway:
adc sync -f adc.yaml
- Gateway API
- APISIX CRD
apiVersion: v1
kind: Service
metadata:
namespace: aic
name: httpbin-external-domain
spec:
type: ExternalName
externalName: httpbin.org
---
apiVersion: apisix.apache.org/v1alpha1
kind: PluginConfig
metadata:
namespace: aic
name: limit-count-advanced-plugin-config
spec:
plugins:
- name: limit-count-advanced
config:
count: 1
time_window: 30
rejected_code: 429
key: remote_addr
policy: redis-cluster
redis_cluster_nodes:
- "redis-cluster-0.redis-cluster.aic.svc:6379"
- "redis-cluster-1.redis-cluster.aic.svc:6379"
redis_password: "p@ssw0rd"
redis_cluster_name: "redis-cluster"
redis_cluster_ssl: true
window_type: sliding
sync_interval: 0.2
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
namespace: aic
name: limit-count-route
spec:
parentRefs:
- name: apisix
rules:
- matches:
- path:
type: Exact
value: /get
filters:
- type: ExtensionRef
extensionRef:
group: apisix.apache.org
kind: PluginConfig
name: limit-count-advanced-plugin-config
backendRefs:
- name: httpbin-external-domain
port: 80
apiVersion: apisix.apache.org/v2
kind: ApisixUpstream
metadata:
namespace: aic
name: httpbin-external-domain
spec:
ingressClassName: apisix
externalNodes:
- type: Domain
name: httpbin.org
---
apiVersion: apisix.apache.org/v2
kind: ApisixRoute
metadata:
namespace: aic
name: limit-count-route
spec:
ingressClassName: apisix
http:
- name: limit-count-route
match:
paths:
- /get
methods:
- GET
upstreams:
- name: httpbin-external-domain
plugins:
- name: limit-count-advanced
config:
count: 1
time_window: 30
rejected_code: 429
key: remote_addr
policy: redis-cluster
redis_cluster_nodes:
- "redis-cluster-0.redis-cluster.aic.svc:6379"
- "redis-cluster-1.redis-cluster.aic.svc:6379"
redis_password: "p@ssw0rd"
redis_cluster_name: "redis-cluster"
redis_cluster_ssl: true
window_type: sliding
sync_interval: 0.2
Apply the configuration:
kubectl apply -f limit-count-advanced-ic.yaml
❶ policy: Set to redis-cluster to use a Redis cluster for rate limiting.
❷ redis_cluster_nodes: Set to Redis node addresses in the Redis cluster.
❸ redis_password: Set to the password of the Redis cluster, if any.
❹ redis_cluster_name: Set to the Redis cluster name.
➎ redis_cluster_ssl: Enable SSL/TLS communication with Redis cluster.
❻ window_type: Set the window type to sliding window.
❼ sync_interval: Set the synchronization interval (optional).
Generate 7 requests to the route every other second:
for i in $(seq 7); do
(curl -I "http://127.0.0.1:9080/get" &)
sleep 1
done
You should receive HTTP/1.1 200 OK responses for most requests, with the remainder being HTTP 429 Too Many Requests responses. The specific number rejected depends on when the first request is sent. This verifies routes configured in different gateway nodes share the same quota.
Customize Rate Limiting Headers
The following example demonstrates how you can use plugin metadata to customize the rate limiting response header names, which are by default X-RateLimit-Limit, X-RateLimit-Remaining, and X-RateLimit-Reset.
This example assumes a route /get with the limit-count-advanced plugin already exists.
- Admin API
- ADC
- Ingress Controller
curl "http://127.0.0.1:9180/apisix/admin/plugin_metadata/limit-count-advanced" -X PUT -d '
{
"log_format": {
"limit_header": "X-Custom-RateLimit-Limit",
"remaining_header": "X-Custom-RateLimit-Remaining",
"reset_header": "X-Custom-RateLimit-Reset"
}
}'
... # other ADC configs
plugin_metadata:
limit-count-advanced:
limit_header: X-Custom-RateLimit-Limit
remaining_header: X-Custom-RateLimit-Remaining
reset_header: X-Custom-RateLimit-Reset
Synchronize the configuration to the gateway:
adc sync -f adc.yaml
- Gateway API
- APISIX CRD
Update your GatewayProxy manifest for the plugin metadata:
apiVersion: apisix.apache.org/v1alpha1
kind: GatewayProxy
metadata:
namespace: aic
name: apisix-config
spec:
provider:
type: ControlPlane
controlPlane:
# add your control plane connection configuration here
# ....
pluginMetadata:
limit-count-advanced:
log_format:
limit_header: X-Custom-RateLimit-Limit
remaining_header: X-Custom-RateLimit-Remaining
reset_header: X-Custom-RateLimit-Reset
Apply the configuration:
kubectl apply -f gatewayproxy.yaml
Send a request to verify:
curl -i "http://127.0.0.1:9080/get"
You should receive an HTTP/1.1 200 OK response and see the following headers:
X-Custom-RateLimit-Limit: 1
X-Custom-RateLimit-Remaining: 0
X-Custom-RateLimit-Reset: 28
Share Quota Among Gateway Nodes with Redis Sentinel
The following example demonstrates how you can use limit-count-advanced plugin with Redis Sentinel policy for rate limiting.
Ensure that your Redis instances are running in Sentinel mode.
Create a route with the following configurations in the gateway group:
- Admin API
- ADC
- Ingress Controller
curl "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d '{
"id": "limit-count-route",
"uri": "/get",
"plugins": {
"limit-count-advanced": {
"count": 1,
"time_window": 30,
"rejected_code": 429,
"key": "remote_addr",
"policy": "redis-sentinel",
"redis_sentinels": [
{"host": "127.0.0.1", "port": 26379},
{"host": "127.0.10.1", "port": 26379},
{"host": "127.0.101.1", "port": 26379}
],
"redis_master_name": "mymaster",
"redis_role": "master",
"sentinel_username": "admin",
"sentinel_password": "admin-password"
}
},
"upstream": {
"type": "roundrobin",
"nodes": {
"httpbin.org:80": 1
}
}
}'
services:
- name: httpbin
routes:
- uris:
- /get
name: limit-count-route
plugins:
limit-count-advanced:
count: 1
time_window: 30
rejected_code: 429
key: remote_addr
policy: redis-sentinel
redis_sentinels:
- host: "127.0.0.1"
port: 26379
- host: "127.0.10.1"
port: 26379
- host: "127.0.101.1"
port: 26379
redis_master_name: "mymaster"
redis_role: "master"
sentinel_username: "admin"
sentinel_password: "admin-password"
upstream:
type: roundrobin
nodes:
- host: httpbin.org
port: 80
weight: 1
Synchronize the configuration to the gateway:
adc sync -f adc.yaml
- Gateway API
- APISIX CRD
apiVersion: v1
kind: Service
metadata:
namespace: aic
name: httpbin-external-domain
spec:
type: ExternalName
externalName: httpbin.org
---
apiVersion: apisix.apache.org/v1alpha1
kind: PluginConfig
metadata:
namespace: aic
name: limit-count-advanced-plugin-config
spec:
plugins:
- name: limit-count-advanced
config:
count: 1
time_window: 30
rejected_code: 429
key: remote_addr
policy: redis-sentinel
redis_sentinels:
- host: "redis-sentinel-0.redis-sentinel.aic.svc"
port: 26379
- host: "redis-sentinel-1.redis-sentinel.aic.svc"
port: 26379
- host: "redis-sentinel-2.redis-sentinel.aic.svc"
port: 26379
redis_master_name: "mymaster"
redis_role: "master"
sentinel_username: "admin"
sentinel_password: "admin-password"
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
namespace: aic
name: limit-count-route
spec:
parentRefs:
- name: apisix
rules:
- matches:
- path:
type: Exact
value: /get
filters:
- type: ExtensionRef
extensionRef:
group: apisix.apache.org
kind: PluginConfig
name: limit-count-advanced-plugin-config
backendRefs:
- name: httpbin-external-domain
port: 80
apiVersion: apisix.apache.org/v2
kind: ApisixUpstream
metadata:
namespace: aic
name: httpbin-external-domain
spec:
ingressClassName: apisix
externalNodes:
- type: Domain
name: httpbin.org
---
apiVersion: apisix.apache.org/v2
kind: ApisixRoute
metadata:
namespace: aic
name: limit-count-route
spec:
ingressClassName: apisix
http:
- name: limit-count-route
match:
paths:
- /get
methods:
- GET
upstreams:
- name: httpbin-external-domain
plugins:
- name: limit-count-advanced
config:
count: 1
time_window: 30
rejected_code: 429
key: remote_addr
policy: redis-sentinel
redis_sentinels:
- host: "redis-sentinel-0.redis-sentinel.aic.svc"
port: 26379
- host: "redis-sentinel-1.redis-sentinel.aic.svc"
port: 26379
- host: "redis-sentinel-2.redis-sentinel.aic.svc"
port: 26379
redis_master_name: "mymaster"
redis_role: "master"
sentinel_username: "admin"
sentinel_password: "admin-password"
Apply the configuration:
kubectl apply -f limit-count-advanced-ic.yaml
❶ policy: Set to redis-sentinel to use a Redis in sentinel mode for rate limiting.
❷ redis_sentinels: Configure a list of Sentinel node addresses (host and port).
❸ redis_master_name: Configure the name of the Redis master group that Sentinels are monitoring.
❹ redis_role: Set to master to connect to the current Redis master.
❺ sentinel_username: Configure the username used to authenticate with Redis Sentinel.
❻ sentinel_password: Configure the password used to authenticate with Redis Sentinel.
Generate 5 requests to the route every other second:
for i in $(seq 5); do
(curl -I "http://127.0.0.1:9080/get" &)
sleep 1
done
You should receive an HTTP/1.1 200 OK response for one request in a 30-second window, while the rest being HTTP 429 Too Many Requests responses.
Rate Limit by Rules
The following example demonstrates how you can configure limit-count-advanced to apply different rate-limiting rules (available from API7 Enterprise 3.8.17) based on request attributes. In this example, rate limits are applied based on HTTP header values that represent the caller’s access tier.
Note that all rules are applied sequentially. If a configured key does not exist, the corresponding rule will be skipped.
In addition to HTTP headers, you can also base rules on other built-in variables to implement more flexible and fine-grained rate-limiting strategies.
Create a route with the limit-count-advanced plugin that applies different rate limits based on request headers, allowing requests to be rate limited per subscription (X-Subscription-ID) and enforcing a stricter limit for trial users (X-Trial-ID):
- Admin API
- ADC
- Ingress Controller
curl "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d '{
"id": "limit-count-rules-route",
"uri": "/get",
"plugins": {
"limit-count-advanced": {
"policy": "local",
"rejected_code": 429,
"rules": [
{
"key": "${http_x_subscription_id}",
"count": "${http_x_custom_count ?? 5}",
"time_window": 60
},
{
"key": "${http_x_trial_id}",
"count": 1,
"time_window": 60
}
]
}
},
"upstream": {
"type": "roundrobin",
"nodes": {
"httpbin.org:80": 1
}
}
}'
services:
- name: httpbin
routes:
- uris:
- /get
name: limit-count-rules-route
plugins:
limit-count-advanced:
policy: local
rejected_code: 429
rules:
- key: "${http_x_subscription_id}"
count: "${http_x_custom_count ?? 5}"
time_window: 60
- key: "${http_x_trial_id}"
count: 1
time_window: 60
upstream:
type: roundrobin
nodes:
- host: httpbin.org
port: 80
weight: 1
Synchronize the configuration to the gateway:
adc sync -f adc.yaml
- Gateway API
- APISIX CRD
apiVersion: v1
kind: Service
metadata:
namespace: aic
name: httpbin-external-domain
spec:
type: ExternalName
externalName: httpbin.org
---
apiVersion: apisix.apache.org/v1alpha1
kind: PluginConfig
metadata:
namespace: aic
name: limit-count-advanced-plugin-config
spec:
plugins:
- name: limit-count-advanced
config:
policy: local
rejected_code: 429
rules:
- key: "${http_x_subscription_id}"
count: "${http_x_custom_count ?? 5}"
time_window: 60
- key: "${http_x_trial_id}"
count: 1
time_window: 60
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
namespace: aic
name: limit-count-rules-route
spec:
parentRefs:
- name: apisix
rules:
- matches:
- path:
type: Exact
value: /get
filters:
- type: ExtensionRef
extensionRef:
group: apisix.apache.org
kind: PluginConfig
name: limit-count-advanced-plugin-config
backendRefs:
- name: httpbin-external-domain
port: 80
apiVersion: apisix.apache.org/v2
kind: ApisixUpstream
metadata:
namespace: aic
name: httpbin-external-domain
spec:
ingressClassName: apisix
externalNodes:
- type: Domain
name: httpbin.org
---
apiVersion: apisix.apache.org/v2
kind: ApisixRoute
metadata:
namespace: aic
name: limit-count-rules-route
spec:
ingressClassName: apisix
http:
- name: limit-count-rules-route
match:
paths:
- /get
methods:
- GET
upstreams:
- name: httpbin-external-domain
plugins:
- name: limit-count-advanced
config:
policy: local
rejected_code: 429
rules:
- key: "${http_x_subscription_id}"
count: "${http_x_custom_count ?? 5}"
time_window: 60
- key: "${http_x_trial_id}"
count: 1
time_window: 60
Apply the configuration:
kubectl apply -f limit-count-advanced-ic.yaml
❶ Use the value of the X-Subscription-ID request header as the rate-limiting key.
❷ Set the request limit dynamically based on the X-Custom-Count header. If the header is not provided, a default count of 5 requests is applied.
❸ Use the value of the X-Trial-ID request header as the rate-limiting key.
To verify rate limiting, generate 7 requests to the route with the same subscription ID:
resp=$(seq 7 | xargs -I{} curl "http://127.0.0.1:9080/get" -H "X-Subscription-ID: sub-123456789" -o /dev/null -s -w "%{http_code}\n") && \
count_200=$(echo "$resp" | grep "200" | wc -l) && \
count_429=$(echo "$resp" | grep "429" | wc -l) && \
echo "200": $count_200, "429": $count_429
You should see the following response, showing that the default count of 5 requests is applied when X-Custom-Count header is not provided:
200: 5, 429: 2
Wait for the time window to reset. Generate 5 requests to the route with the same subscription ID and set the X-Custom-Count header to 3:
resp=$(seq 5 | xargs -I{} curl "http://127.0.0.1:9080/get" -H "X-Subscription-ID: sub-123456789" -H "X-Custom-Count: 3" -o /dev/null -s -w "%{http_code}\n") && \
count_200=$(echo "$resp" | grep "200" | wc -l) && \
count_429=$(echo "$resp" | grep "429" | wc -l) && \
echo "200": $count_200, "429": $count_429
You should see the following response, showing that the count of 3 requests from the X-Custom-Count header is applied:
200: 3, 429: 2
Finally, generate 3 requests to the route with the same trial ID:
resp=$(seq 3 | xargs -I{} curl "http://127.0.0.1:9080/get" -H "X-Trial-ID: trial-123456789" -o /dev/null -s -w "%{http_code}\n") && \
count_200=$(echo "$resp" | grep "200" | wc -l) && \
count_429=$(echo "$resp" | grep "429" | wc -l) && \
echo "200": $count_200, "429": $count_429
You should see the following response, showing that the count of 1 request from the second rule is applied:
200: 1, 429: 2