limit-conn
Limits concurrent connections per key.
limit-connPriority 1003What it does
limit-conn caps how many requests from one key are open at once on a route, sent and not yet answered. Under One ceiling for everything here, Conn is that ceiling, Burst is how many more wait instead of being refused, and the key tells callers apart, for example remote_addr.
A waiting request is held for Default connection delay and then let through. A request beyond the burst is answered by the gateway itself with Rejected code, 503 unless you set another, as How G8 handles a request describes.
When to use it
- A backend that serves a fixed number of requests at a time, where more in flight from one client would hold every worker.
- Slow paths, a report export for example, that one client could fill by opening many requests at once.
- One ceiling for each tenant and another for each client address, under A ceiling for each key, with keys like
tenant-$http_x_tenantand$remote_addr. - A ceiling that several gateway nodes count together, through one Redis server or a Redis cluster.
Not for a quota counted per time window, for example 100 requests a minute — see limit-count (Limits the number of requests in a time window, per key) or a steady rate per second with a burst that waits its turn — see limit-req (Limits the request rate with a leaky bucket).
Set it up
Allow 20 open connections for each client address and let 5 more wait
Under Basics choose One ceiling for everything here, set Conn to 20, set Burst to 5, set Key to remote_addr and set Default connection delay to 0.5 seconds. Under Behavior set Rejected code to 429.
{
"conn": 20,
"burst": 5,
"default_conn_delay": 0.5,
"key": "remote_addr",
"rejected_code": 429
}
More scenarios
Give each tenant its own connection ceiling and each client address another
The tenant header has to be set by a trusted layer in front and stripped from client requests; a client that sends no tenant header is counted under the per-address ceiling alone.
Under Basics choose A ceiling for each key, fill Rules as in the JSON below and set Default connection delay to 0.5 seconds.
{
"default_conn_delay": 0.5,
"rules": [
{
"conn": 50,
"burst": 10,
"key": "tenant-$http_x_tenant"
},
{
"conn": 20,
"burst": 0,
"key": "$remote_addr"
}
]
}
Things to know
- Rejected code — Set to
429, with a ceiling of 20 and 5 more waiting, 40 requests sent at once to/delay/1are answered partly200and partly429. - Rejected code — Unset, a request beyond the burst is answered
503, the answer of a service that is unavailable. - Conn — A reference with text around it, for example
abc${http_x_conn}, is refused when you save. - Conn — A ceiling of
0is refused when you save. - Key — A variable the request does not carry, or a name with a dollar sign under Variable, is saved without a word, and every request is then counted by client address. So is a combination in which no $name resolves.
- Rules — Rules cannot be set beside Conn, Burst and Key; the save is refused.
- Rules — An empty list of rules is refused when you save.
- Key — A rule's key holds at least one $variable,
$remote_addrand notremote_addr. A key that names none is refused when you save. - Allow degradation — When the limit cannot be counted, because the store is unreachable or a value resolves to nothing, off answers 500 and on lets every request through unlimited.
- AdviceLet a trusted layer in front of the gateway set a tenant header like
X-Tenantand strip it from client requests, so that a client cannot choose the ceiling it is counted under. - AdviceBehind a load balancer, add real-ip to the same route, so that each client is held to the ceiling by its own address and not by the load balancer's.
Settings
The fields as the console shows them, section by section. A field under “When … is …” is there only while that value is set.
Basics
Choose one:
One ceiling for everything here
conninteger or stringRequiredHow many requests one key may have in flight at once, such as 20. A $variable or ${variable} is read on every request, and a request without it fails with 500. $env://NAME is read once when the configuration loads.
pattern
^([0-9]*[1-9][0-9]*|[$](env|secret)://.+|[$][{][^}]*[}]|[$][A-Za-z_][A-Za-z0-9_.]*)$burstinteger or stringRequiredHow many connections beyond Conn wait instead of being refused; 0 refuses every one beyond Conn.
pattern
^([0-9]+|[$](env|secret)://.+|[$][{][^}]*[}]|[$][A-Za-z_][A-Za-z0-9_.]*)$keystringRequiredThe variable that tells callers apart, such as remote_addr; with Key type var combination, a template such as $remote_addr $server_port. Not read when Rules carries entries.
remote_addrA ceiling for each key
rulesarray of objectsRequiredOne ceiling per entry, each with its own Conn, Burst and key template, such as $http_x_api_key. Rules cannot be stored together with Conn, Burst and Key: the engine refuses the pair. Key type is ignored for rules.
rules[].burstinteger or stringRequiredHow many connections beyond Conn this entry lets wait instead of refusing. Zero is a value.
pattern
^([0-9]+|[$](env|secret)://.+|[$][{][^}]*[}]|[$][A-Za-z_][A-Za-z0-9_.]*)$rules[].conninteger or stringRequiredHow many connections this entry allows at once. May be written as a $variable, ${variable} or $env://NAME, like Conn.
pattern
^([0-9]*[1-9][0-9]*|[$](env|secret)://.+|[$][{][^}]*[}]|[$][A-Za-z_][A-Za-z0-9_.]*)$rules[].keystringRequiredA template holding at least one $variable, expanded on every request. An entry whose key expands no variable is dropped and limits nothing.
pattern
[$]([{][^}]+[}]|[A-Za-z_][A-Za-z0-9_.]*)key_typestringdefault varWhether Key is one variable name or a template of several. Not read when Rules carries entries.
default_conn_delaynumberRequiredHow long a waiting connection is held before it is let through.
Behavior
policystringdefault localWhen Policy is redis
key_ttlintegerdefault 3600How long a connection count stays on the Redis server after its last use.
redis_databaseintegerdefault 0redis_hoststringRequiredredis_keepalive_poolintegerdefault 100redis_keepalive_timeoutintegerdefault 10000redis_usernamestringredis_passwordstringStored on the engine and shown only to roles that manage this object.
redis_portintegerdefault 6379redis_sslbooleandefault falseredis_ssl_verifybooleandefault falseredis_server_namestringThe server name sent in the TLS handshake and, with verification on, checked against the certificate; unset, the host is sent, and an address never is.
redis_timeoutintegerdefault 1000When Policy is redis-cluster· 9 fields
key_ttlintegerdefault 3600How long a connection count stays on the Redis server after its last use.
redis_cluster_namestringRequiredredis_cluster_nodesarray of stringsRequiredredis_cluster_sslbooleandefault falseredis_cluster_ssl_verifybooleandefault falseredis_keepalive_poolintegerdefault 100redis_keepalive_timeoutintegerdefault 10000redis_passwordstringStored on the engine and shown only to roles that manage this object.
redis_timeoutintegerdefault 1000rejected_codeintegerdefault 503rejected_msgstringText the client reads in the JSON body of a refused request, such as Too many connections. Left empty, 503 and 429 are answered with the server's HTML error page and any other code with an empty body.
allow_degradationbooleandefault falseLet requests through when the limit cannot be counted, rather than answering 500.
Advanced
only_use_default_delaybooleandefault falseHold every waiting connection for the default delay, rather than for a delay measured from how long the upstream took.