Skip to main content
Version: 3.9.x

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.

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"
}
}
}'

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.

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
}
}
}'

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.

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"
}
]
}
}
}'

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-count key type: For limit-count, set key_type to var when key names a request variable such as remote_addr, or to constant when key is a literal value.
  • Invalid limit-count-advanced rule key: A rule has no key_type. Its key is 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 HTTP 500 by default.
  • Latency with Redis: If Redis latency is affecting request performance, consider using the local policy for high-frequency low-latency limits, or tune the sync_interval for redis-based policies.

Next Steps​