Apply Rate Limiting to APIs
Applying rate limiting controls the number of requests sent to your API backend. This protects your backend from too much traffic, both wanted and unwanted (web crawlers, DDoS attacks), which can result in operational inefficiencies and higher costs.
This guide walks you through applying rate limits to control the requests sent to your upstream nodes over time.
Prerequisites
Apply Rate Limiting for All Services (Not Recommended)
You should not configure rate-limiting plugins globally, as different APIs typically require different rate-limiting quotas. If you configure the same plugin globally (in a global rule) and locally (in a route), the API7 Gateway executes both plugin instances sequentially.
Apply Rate Limiting for a Single Route
Limit Request Count
This section configures a route with rate limiting to only allow 3 requests in 60 seconds. When the limit is exceeded, a 429 status code is returned to the consumer.
- Dashboard
- ADC
- Ingress Controller
- Select Published Services of your gateway group from the side navigation bar, then click the service you want to modify, for example,
httpbin
with version1.0.0
. - Under the published service, select Routes from the side navigation bar.
- Select your target route, for example,
get-ip
. - In the Plugin field, click Enable Plugin.
- Search for the Limit Count Plugin, then click Enable.
- In the dialog box, do the following:
Add the following configuration to the JSON Editor:
{
"count": 3,
"time_window": 60,
"key_type": "var",
"key": "remote_addr",
"rejected_code": 429,
"rejected_msg": "Too many requests",
"policy": "local",
"allow_degradation": false,
"show_limit_quota_header": true
}Click Enable.
Below is an interactive demo that provides a hands-on introduction to limiting request numbers. You will gain a better understanding of how to use it in API7 Enterprise by clicking and following the steps.
To use ADC to configure the route, create the following configuration:
services:
- name: httpbin
upstream:
name: default
scheme: http
nodes:
- host: httpbin.org
port: 80
weight: 100
routes:
- uris:
- /ip
name: get-ip
methods:
- GET
plugins:
limit-count:
_meta:
disable: false
count: 3
time_window: 60
key_type: var
key: remote_addr
policy: local
rejected_code: 429
rejected_msg: Too many requests
allow_degradation: false
show_limit_quota_header: true
Synchronize the configuration to API7 Enterprise:
adc sync -f adc.yaml
Create a Kubernetes manifest file for a route, where rate limiting is enabled:
apiVersion: apisix.apache.org/v2
kind: ApisixRoute
metadata:
name: get-ip
# namespace: api7 # replace with your namespace
spec:
http:
- name: get-ip
match:
paths:
- /ip
methods:
- GET
backends:
- serviceName: httpbin
servicePort: 80
plugins:
- name: limit-count
enable: true
config:
count: 3
time_window: 60
key_type: var
key: remote_addr
policy: local
rejected_code: 429
rejected_msg: Too many requests
allow_degradation: false
show_limit_quota_header: true
Apply the configurations to your cluster:
kubectl apply -f httpbin-route.yaml
Validate
To validate, send five consecutive requests:
resp=$(seq 5 | xargs -I{} curl "http://127.0.0.1:9080/ip" -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 out of the 5 requests, 3 requests were successful (status code 200) while the others were rejected (status code 429).
200: 3, 429: 2
Limit Requests per Second
This section configures a route with rate-limiting to only allow 1 request per second. When the number of requests per second is between 1 and 3 they will be delayed/throttled. When the number of requests per second is more than 3, a 429 status code is returned.
- Dashboard
- ADC
- Ingress Controller
- Select Published Services of your gateway group from the side navigation bar, then select the service you want to modify, for example,
httpbin
with version1.0.0
. - Under the published service, select Routes from the side navigation bar.
- Select your target route, for example,
get-ip
. - In the Plugin field, click Enable Plugin.
- Search for the Limit Req Plugin, then click Enable.
- In the dialog box, do the following:
Add the following configuration to the JSON Editor:
{
"rate": 1,
"burst": 2,
"key_type": "var",
"key": "remote_addr",
"rejected_code": 429,
"rejected_msg": "Requests are too frequent, please try again later."
}Click Enable.
To use ADC to configure the route, create the following configuration:
services:
- name: httpbin
upstream:
name: default
scheme: http
nodes:
- host: httpbin.org
port: 80
weight: 100
routes:
- uris:
- /ip
name: get-ip
methods:
- GET
plugins:
limit-req:
_meta:
disable: false
rate: 1
burst: 2
key_type: var
key: remote_addr
rejected_code: 429
rejected_msg: Requests are too frequent, please try again later.
Synchronize the configuration to API7 Gateway:
adc sync -f adc.yaml
Create a Kubernetes manifest file for a route, where rate limiting is enabled:
apiVersion: apisix.apache.org/v2
kind: ApisixRoute
metadata:
name: get-ip
# namespace: api7 # replace with your namespace
spec:
http:
- name: get-ip
match:
paths:
- /ip
methods:
- GET
backends:
- serviceName: httpbin
servicePort: 80
plugins:
- name: limit-req
enable: true
config:
rate: 1
burst: 2
key_type: var
key: remote_addr
rejected_code: 429
rejected_msg: Requests are too frequent, please try again later.
Apply the configurations to your cluster:
kubectl apply -f httpbin-route.yaml
Validate
To validate, send three requests to the route:
resp=$(seq 3 | xargs -I{} curl -i "http://127.0.0.1:9080/ip" -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 responses: $count_200 ; 429 responses: $count_429"
You are likely to see that all three requests are successful:
200 responses: 3 ; 429 responses: 0
Update burst
in the plugin configuration to 0
, then send three requests to the route:
resp=$(seq 3 | xargs -I{} curl -i "http://127.0.0.1:9080/ip" -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 responses: $count_200 ; 429 responses: $count_429"
You should see a response similar to the following, showing requests surpassing the rate have been rejected:
200 responses: 1 ; 429 responses: 2
Rate Limit with Consumers
The following example demonstrates how you can configure different rate limiting policies by consumers. While this example uses Key Auth Plugin for authentication, the route can also be configured with Basic Auth Plugin, JWT Auth Plugin, and HMAC Auth Plugin.
Add a Consumer
Create a regular consumer Alice
with key authentication credential, and configure the Limit Count Plugin to allow for a quota of 3 within a 60-second window:
- Dashboard
- ADC
- Ingress Controller
- Select Consumers of your gateway group from the side navigation bar.
- Click Add Consumer.
- From the dialog box, do the following:
- In the Name field, enter
Alice
. - Click Add.
- In the Plugins field, click Enable Plugin.
- Search for the Key Auth Plugin, then click Enable.
- In the dialog box, do the following:
Add the following configuration to the JSON Editor:
{
"key": "alice-key"
}Click Enable.
- Search for the Limit Count Plugin, then click Enable.
- In the dialog box, do the following:
Add the following configuration to the JSON Editor:
{
"count": 3,
"time_window": 60,
"key_type": "var",
"key": "remote_addr",
"rejected_code": 429,
"rejected_msg": "Too many requests",
"policy": "local",
"allow_degradation": false,
"show_limit_quota_header": true
}Click Enable.
To use ADC to create a consumer, create the following configuration:
consumers:
- username: Alice
plugins:
key-auth:
_meta:
disable: false
key: alice-key
limit-count:
_meta:
disable: false
count: 3
time_window: 60
key_type: var
key: remote_addr
rejected_code: 429
rejected_msg: Too many requests
policy: local
allow_degradation: false
show_limit_quota_header: true
Synchronize the configuration to API7 Gateway:
adc sync -f adc-consumer.yaml
Create a Kubernetes manifest file to configure a consumer using the ApisixConsumer custom resource:
apiVersion: apisix.apache.org/v2
kind: ApisixConsumer
metadata:
name: alice
# namespace: api7 # replace with your namespace
spec:
authParameter:
keyAuth:
value:
key: "alice-key"
Apply the configurations to your cluster:
kubectl apply -f consumer.yaml
Configure Route
Create a route and configure the Key Auth Plugin for authentication:
- Dashboard
- ADC
- Ingress Controller
- Select Published Services of your gateway group from the side navigation bar, then click the service you want to modify, for example,
httpbin
with version1.0.0
. - Under the published service, select Routes from the side navigation bar.
- Select your target route, for example,
get-ip
. - In the Plugin field, click Enable Plugin.
- Search for the Key Auth Plugin, then click Enable.
- In the dialog box, do the following:
Add the following configuration to the JSON Editor:
{
}Click Enable.
To use ADC to configure the route, create the following configuration:
services:
- name: httpbin
upstream:
name: default
scheme: http
nodes:
- host: httpbin.org
port: 80
weight: 100
routes:
- uris:
- /ip
name: get-ip
methods:
- GET
plugins:
key-auth:
_meta:
disable: false
Synchronize the configuration to API7 Gateway:
adc sync -f adc.yaml
Create a Kubernetes manifest file for a route, where rate limiting is enabled:
apiVersion: apisix.apache.org/v2
kind: ApisixRoute
metadata:
name: get-ip
# namespace: api7 # replace with your namespace
spec:
http:
- name: get-ip
match:
paths:
- /ip
methods:
- GET
backends:
- serviceName: httpbin
servicePort: 80
plugins:
- name: key-auth
enable: true
Apply the configurations to your cluster:
kubectl apply -f httpbin-route.yaml
Validate
To validate, send five consecutive requests with Alice
's key:
resp=$(seq 5 | xargs -I{} curl "http://127.0.0.1:9080/ip" -H 'apikey: alice-key' -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 out of the 5 requests, 3 requests were successful (status code 200) while the others were rejected (status code 429).
200: 3, 429: 2