Configure Rate Limiting
Rate limiting allows you to restrict the number of requests a client can make to your APIs within a specific time window. This protects your backend services from being overwhelmed by too many requests and ensures fair usage among all users.
API7 Enterprise provides two plugins for rate limiting:
limit-count: A simple rate limiting plugin that counts requests within a fixed time window.limit-count-advanced: An advanced version that supports sliding windows, multiple rules, and Redis Sentinel.
The scenarios below reuse one service and route. Verify each scenario before applying the next one because a later scenario updates the route's plugin configuration and becomes the only active rate limiter.
Prerequisites
- An API7 Enterprise instance is running.
- A Gateway Group is created and a Gateway instance is running.
- A token from the Dashboard.
Configure Basic Rate Limiting
The limit-count plugin is ideal for simple rate limiting scenarios, such as limiting each IP address to 5 requests per minute.
- Admin API
- ADC
curl -k "https://localhost:7443/apisix/admin/services/rate-limit-service?gateway_group_id={gateway_group_id}" -X PUT \
-H "X-API-KEY: ${API_KEY}" \
-H "Content-Type: application/json" \
-d '{
"name": "rate-limit-service",
"upstream": {
"type": "roundrobin",
"scheme": "http",
"nodes": [
{
"host": "httpbin.org",
"port": 80,
"weight": 100
}
]
}
}'
curl -k "https://localhost:7443/apisix/admin/routes/rate-limit-route?gateway_group_id={gateway_group_id}" -X PUT \
-H "X-API-KEY: ${API_KEY}" \
-H "Content-Type: application/json" \
-d '{
"name": "rate-limit-route",
"methods": ["GET"],
"paths": ["/get"],
"service_id": "rate-limit-service",
"plugins": {
"limit-count": {
"count": 5,
"time_window": 60,
"rejected_code": 429,
"rejected_msg": "Too Many Requests",
"key": "remote_addr",
"policy": "local"
}
}
}'
services:
- name: rate-limit-service
upstream:
nodes:
- host: httpbin.org
port: 80
weight: 1
routes:
- name: rate-limit-route
uris:
- /get
methods:
- GET
plugins:
limit-count:
count: 5
time_window: 60
rejected_code: 429
rejected_msg: "Too Many Requests"
key_type: var
key: remote_addr
policy: local
labels:
docs-example: rate-limit-service
Preview the changes owned by this example and confirm that the diff contains no unintended updates or deletions:
adc diff -f adc.yaml \
--include-resource-type service \
--label-selector docs-example=rate-limit-service
Synchronize the reviewed configuration:
adc sync -f adc.yaml \
--include-resource-type service \
--label-selector docs-example=rate-limit-service
Send six GET requests. The first five requests should succeed and the sixth should return 429:
for i in {1..6}; do
curl -s -o /dev/null -w '%{http_code}\n' "http://127.0.0.1:9080/get"
done
Configure Distributed Rate Limiting
In a multi-node Gateway deployment, use the redis policy to share the rate limit counters across all nodes.
- Admin API
- ADC
curl -k "https://localhost:7443/apisix/admin/services/rate-limit-service?gateway_group_id={gateway_group_id}" -X PUT \
-H "X-API-KEY: ${API_KEY}" \
-H "Content-Type: application/json" \
-d '{
"name": "rate-limit-service",
"upstream": {
"type": "roundrobin",
"scheme": "http",
"nodes": [
{
"host": "httpbin.org",
"port": 80,
"weight": 100
}
]
}
}'
curl -k "https://localhost:7443/apisix/admin/routes/rate-limit-route?gateway_group_id={gateway_group_id}" -X PUT \
-H "X-API-KEY: ${API_KEY}" \
-H "Content-Type: application/json" \
-d '{
"name": "rate-limit-route",
"methods": ["GET"],
"paths": ["/get"],
"service_id": "rate-limit-service",
"plugins": {
"limit-count": {
"count": 5,
"time_window": 60,
"rejected_code": 429,
"policy": "redis",
"redis_host": "127.0.0.1",
"redis_port": 6379,
"redis_password": "your-password",
"redis_database": 0,
"allow_degradation": true
}
}
}'
services:
- name: rate-limit-service
upstream:
nodes:
- host: httpbin.org
port: 80
weight: 1
routes:
- name: rate-limit-route
uris:
- /get
methods:
- GET
plugins:
limit-count:
count: 5
time_window: 60
rejected_code: 429
policy: redis
redis_host: "127.0.0.1"
redis_port: 6379
redis_password: "your-password"
redis_database: 0
allow_degradation: true
labels:
docs-example: rate-limit-service
Preview the changes owned by this example and confirm that the diff contains no unintended updates or deletions:
adc diff -f adc.yaml \
--include-resource-type service \
--label-selector docs-example=rate-limit-service
Synchronize the reviewed configuration:
adc sync -f adc.yaml \
--include-resource-type service \
--label-selector docs-example=rate-limit-service
Set allow_degradation to true to allow traffic even if the Redis server is unreachable.
After confirming that Redis is reachable, send six GET requests. The first five requests should succeed and the sixth should return 429:
for i in {1..6}; do
curl -s -o /dev/null -w '%{http_code}\n' "http://127.0.0.1:9080/get"
done
Configure Advanced Rate Limiting
The limit-count-advanced plugin supports a sliding window algorithm, which prevents traffic bursts that can occur at the boundary of fixed windows. It also allows defining multiple rules in a single plugin instance.
- Admin API
- ADC
curl -k "https://localhost:7443/apisix/admin/services/rate-limit-service?gateway_group_id={gateway_group_id}" -X PUT \
-H "X-API-KEY: ${API_KEY}" \
-H "Content-Type: application/json" \
-d '{
"name": "rate-limit-service",
"upstream": {
"type": "roundrobin",
"scheme": "http",
"nodes": [
{
"host": "httpbin.org",
"port": 80,
"weight": 100
}
]
}
}'
curl -k "https://localhost:7443/apisix/admin/routes/rate-limit-route?gateway_group_id={gateway_group_id}" -X PUT \
-H "X-API-KEY: ${API_KEY}" \
-H "Content-Type: application/json" \
-d '{
"name": "rate-limit-route",
"methods": ["GET"],
"paths": ["/get"],
"service_id": "rate-limit-service",
"plugins": {
"limit-count-advanced": {
"window_type": "sliding",
"policy": "local",
"rejected_code": 429,
"rules": [
{
"count": 3,
"time_window": 60,
"key": "$remote_addr"
},
{
"count": 1000,
"time_window": 3600,
"key": "$http_x_api_key"
}
]
}
}
}'
services:
- name: rate-limit-service
upstream:
nodes:
- host: httpbin.org
port: 80
weight: 1
routes:
- name: rate-limit-route
uris:
- /get
methods:
- GET
plugins:
limit-count-advanced:
window_type: sliding
policy: local
rejected_code: 429
rules:
- count: 3
time_window: 60
key: "$remote_addr"
- count: 1000
time_window: 3600
key: "$http_x_api_key"
labels:
docs-example: rate-limit-service
Preview the changes owned by this example and confirm that the diff contains no unintended updates or deletions:
adc diff -f adc.yaml \
--include-resource-type service \
--label-selector docs-example=rate-limit-service
Synchronize the reviewed configuration:
adc sync -f adc.yaml \
--include-resource-type service \
--label-selector docs-example=rate-limit-service
In this example, each client IP is limited to 3 requests per minute, and each API key is limited to 1,000 requests per hour.
Send four GET requests. The first three requests should succeed and the fourth should return 429:
for i in {1..4}; do
curl -s -o /dev/null -w '%{http_code}\n' "http://127.0.0.1:9080/get" \
-H "X-API-Key: demo-client"
done
Interpret Rate-Limit Responses
The rejected request uses the configured 429 Too Many Requests response.
If the route returns 404 immediately after you apply the configuration, wait a few seconds for the latest configuration to reach the gateway and retry.
The basic and distributed scenarios include X-RateLimit headers if show_limit_quota_header is enabled (default is true):
HTTP/1.1 429 Too Many Requests
X-RateLimit-Limit: 5
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 45
An admitted advanced request that reaches both rules can include one quota-header set for each. Without a configured header_prefix, the rule index is used, such as X-1-RateLimit-Limit for the first rule and X-2-RateLimit-Limit for the second. If the first rule rejects a request, evaluation stops before the second rule, so the rejection response can include only the first rule's header set.
Troubleshooting
- Redis Connection Issues: Ensure the Gateway nodes have network access to the Redis server and that the credentials are correct. Check the Gateway logs for connection errors.
- Wrong
limit-countkey type: Forlimit-count, setkey_typetovarwhenkeynames a request variable such asremote_addr, or toconstantwhenkeyis a literal value. - Invalid
limit-count-advancedrule key: A rule has nokey_type. Itskeyis a variable expression, so prefix variables with$, such as$remote_addr. A value without a variable reference is skipped; if every rule is skipped, the gateway returns HTTP500by default. - Latency with Redis: If Redis latency is affecting request performance, consider using the
localpolicy for high-frequency low-latency limits, or tune thesync_intervalfor redis-based policies.
Next Steps
- Implement Traffic Splitting — route a percentage of traffic to new versions.
- Configure Proxy Rewrite — modify request URIs and headers before proxying.