Rate limiting
The RateLimit plugin allows you to limit the number of requests a client can make within a specified time period.
Ktor provides several ways to configure rate limiting:
Apply a rate limit globally to the entire application or configure different limits for specific resources.
Apply rate limits based on request parameters, such as an IP address, API key or access token.
Add dependencies
To use RateLimit, add the ktor-server-rate-limit artifact to your build script:
Install RateLimit
To install the RateLimit plugin to your application, pass it to the install function in the specified module. The following examples show how to install RateLimit:
In an
embeddedServer()function call.In an explicitly defined
module()extension function on theApplicationclass.
Configure RateLimit
Overview
Ktor uses the token bucket algorithm for rate limiting, which works as follows:
A bucket is created with a specified capacity, which defines the number of available tokens.
Each incoming request consumes one token from the bucket:
If there is enough capacity, the server processes the request and includes the following headers in the response:
X-RateLimit-Limit: the bucket capacity.X-RateLimit-Remaining: the number of tokens remaining in the bucket.X-RateLimit-Reset: the UTC timestamp, in seconds, that specifies when the bucket is refilled.
If there is insufficient capacity, the server rejects a request using a
429 Too Many Requestsresponse. The response includes theRetry-Afterheader, indicating how many seconds the client should wait before sending another request.
After the specified refill period, the bucket is refilled.
Register a rate limiter
You can apply rate limiting globally to the entire application or register a rate limiter for specific routes:
To apply rate limiting globally, call the
global()function and configure the rate limiter:install(RateLimit) { global { rateLimiter(limit = 5, refillPeriod = 60.seconds) } }To configure rate limiting for specific routes, use the
register()function to register a rate limiter:install(RateLimit) { register { rateLimiter(limit = 5, refillPeriod = 60.seconds) } }
The examples above show the minimal configuration required for the RateLimit plugin. If you use register(), you also need to apply the registered rate limiter to a specific route.
Configure rate limiting
You can configure a rate limiter using the options below.
Name a rate limiter
Use the register() function to assign a name to a rate limiter. You can then apply the named rate limiter to specific routes:
Set the limit and refill period
Use the rateLimiter() function to configure the bucket capacity and refill period:
limitspecifies the number of available tokens.refillPeriodspecifies how often the bucket is refilled.
The following example allows up to 30 requests per minute:
Distinguish requests by key
Use the requestKey() function to return a key for each request. Requests with different keys have independent rate limits.
The following example uses the login query parameter to distinguish between users:
Rate limit authenticated users
You can use an authentication principal as a request key to apply rate limits per authenticated user.
Nest rateLimit() inside authenticate(), then access the principal from requestKey():
Set the request weight
Use the requestWeight() function to specify how many tokens each request consumes. The function receives the application call and the request key.
In the following example, requests with the jetbrains key consume one token, while all other requests consume two:
Customize the response
Use the modifyResponse() function to customize the response when rate limiting is applied.
For example, you can add custom rate-limit headers:
Define rate limiting scope
After configuring a rate limiter, you can use the rateLimit() function to apply it to specific routes.
Apply the default rate limiter
Use the rateLimit() function without a name to apply the default registered rate limiter:
Apply a named rate limiter
Pass a RateLimitName to the rateLimit() function to apply a named rate limiter:
Example
The following example shows how to apply different rate limiters to different routes. It configures:
A default rate limiter for the home page.
A named public rate limiter for the public API.
A named protected rate limiter that uses request keys and weights.
The
StatusPagesplugin to customize responses for requests rejected with a429 Too Many Requestsresponse.