Rate limit how many HTTP requests a developer can make in a given period of seconds, minutes, hours, days, months or years. If the underlying Service/Route (or deprecated API entity) has no authentication layer, the Client IP address will be used, otherwise the Consumer will be used if an authentication plugin has been configured.
Configuration Reference
This plugin is partially compatible with DB-less mode.
In DB-less mode, you configure Kong Gateway declaratively. Therefore, the Admin API is mostly read-only. The only tasks it can perform are all related to handling the declarative config, including:
- Setting a target's health status in the load balancer
- Validating configurations against schemas
- Uploading the declarative configuration using the
/config
endpoint
The plugin will run fine with the local
policy (which doesn’t use the database) or
the redis
policy (which uses an independent Redis, so it is compatible with DB-less).
The plugin will not work with the cluster
policy, which requires writes to the database.
Example plugin configuration
Parameters
Here's a list of all the parameters which can be used in this plugin's configuration:
Form Parameter | Description |
---|---|
name
required Type: string |
The name of the plugin, in this case rate-limiting . |
service.name or service.id
Type: string |
The name or ID of the service the plugin targets.
Set one of these parameters if adding the plugin to a service through the top-level /plugins endpoint.
Not required if using /services/SERVICE_NAME|SERVICE_ID/plugins . |
route.name or route.id
Type: string |
The name or ID of the route the plugin targets.
Set one of these parameters if adding the plugin to a route through the top-level /plugins endpoint.
Not required if using /routes/ROUTE_NAME|ROUTE_ID/plugins . |
consumer.name or consumer.id
Type: string |
The name or ID of the consumer the plugin targets.
Set one of these parameters if adding the plugin to a consumer through the top-level /plugins endpoint.
Not required if using /consumers/CONSUMER_NAME|CONSUMER_ID/plugins . |
enabled
Type: boolean Default value: true |
Whether this plugin will be applied. |
config.second
semi-optional |
The amount of HTTP requests the developer can make per second. At least one limit must exist. |
config.minute
semi-optional |
The amount of HTTP requests the developer can make per minute. At least one limit must exist. |
config.hour
semi-optional |
The amount of HTTP requests the developer can make per hour. At least one limit must exist. |
config.day
semi-optional |
The amount of HTTP requests the developer can make per day. At least one limit must exist. |
config.month
semi-optional |
The amount of HTTP requests the developer can make per month. At least one limit must exist. |
config.year
semi-optional |
The amount of HTTP requests the developer can make per year. At least one limit must exist. |
config.limit_by
optional Default value: consumer
|
The entity that will be used when aggregating the limits: |
config.service_id
semi-optional |
The service id to be used if |
config.header_name
semi-optional |
Header name to be used if |
config.policy
optional Default value: cluster
|
The rate-limiting policies to use for retrieving and incrementing the limits. Available values are |
config.fault_tolerant
optional Default value: true
|
A boolean value that determines if the requests should be proxied even if Kong has troubles connecting a third-party datastore. If |
config.hide_client_headers
optional Default value: false
|
Optionally hide informative response headers. |
config.redis_host
semi-optional |
When using the |
config.redis_port
optional Default value: 6379
|
When using the |
config.redis_password
optional |
When using the |
config.redis_timeout
optional Default value: 2000
|
When using the |
config.redis_database
optional Default value: 0
|
When using the |
Headers sent to the client
When this plugin is enabled, Kong will send some additional headers back to the client telling what are the limits allowed, how many requests are available and how long it will take until the quota will be restored, for example:
RateLimit-Limit: 6
RateLimit-Remaining: 4
RateLimit-Reset: 47
The plugin will also send headers telling the limits in the time frame and the number of requests remaining:
X-RateLimit-Limit-Minute: 10
X-RateLimit-Remaining-Minute: 9
or it will return a combination of more time limits, if more than one is being set:
X-RateLimit-Limit-Second: 5
X-RateLimit-Remaining-Second: 4
X-RateLimit-Limit-Minute: 10
X-RateLimit-Remaining-Minute: 9
If any of the limits configured is being reached, the plugin will return a HTTP/1.1 429
status code to the client with the following JSON body:
{ "message": "API rate limit exceeded" }
NOTE:
Implementation considerations
The plugin supports 3 policies, which each have their specific pros and cons.
policy | pros | cons |
---|---|---|
cluster |
accurate, no extra components to support | relatively the biggest performance impact, each request forces a read and a write on the underlying datastore. |
redis |
accurate, lesser performance impact than a cluster policy |
extra redis installation required, bigger performance impact than a local policy |
local |
minimal performance impact | less accurate, and unless a consistent-hashing load balancer is used in front of Kong, it diverges when scaling the number of nodes |
There are 2 use cases that are most common:
- every transaction counts. These are for example transactions with financial consequences. Here the highest level of accuracy is required.
- backend protection. This is where accuracy is not as relevant, but it is merely used to protect backend services from overload. Either by specific users, or to protect against an attack in general.
NOTE:
Every transaction counts
In this scenario, the local
policy is not an option. So here the decision is between
the extra performance of the redis
policy against its extra support effort. Based on that balance,
the choice should either be cluster
or redis
.
The recommendation is to start with the cluster
policy, with the option to move over to redis
if performance reduces drastically. Keep in mind existing usage metrics cannot
be ported from the datastore to redis. Generally with shortlived metrics (per second or per minute)
this is not an issue, but with longer lived ones (months) it might be, so you might want to plan
your switch more carefully.
Backend protection
As accuracy is of lesser importance, the local
policy can be used. It might require some experimenting
to get the proper setting. For example, if the user is bound to 100 requests per second, and you have an
equally balanced 5 node Kong cluster, setting the local
limit to something like 30 requests per second
should work. If you are worried about too many false-negatives, increase the value.
Keep in mind as the cluster scales to more nodes, the users will get more requests granted, and likewise when the cluster scales down the probability of false-negatives increases. So in general, update your limits when scaling.
The above mentioned inaccuracy can be mitigated by using a consistent-hashing load balancer in front of Kong, that ensures the same user is always directed to the same Kong node. This will both reduce the inaccuracy and prevent the scaling issues.
Most likely the user will be granted more than was agreed when using the local
policy, but it will
effectively block any attacks while maintaining the best performance.