The CDI annotation @RateLimit allows you to rate limit method invocations in CDI managed beans
based on a configurable client identifier, such as client IP address, user ID, API key, etc.
This annotation can be applied to both methods and classes. When applied to a class, all methods in that class
will be rate limited unless they have their own @RateLimit annotation which overrides the
class-level configuration.
The rate limiting is enforced by the RateLimitInterceptor which uses a sliding window algorithm
to track request counts per client identifier. When the rate limit is exceeded, the interceptor will by default
immediately throw a RateLimitExceededException. Optionally, you can configure automatic retries via the
maxRetries() attribute, which will retry the request after a calculated delay based on the remaining
time window. If all retries are exhausted, a RateLimitExceededException is thrown.
Usage
Here's an example of rate limiting an API endpoint to 10 requests per minute per client IP:
@Named
@RequestScoped
public class ApiController {
@RateLimit(maxRequestsPerTimeWindow = 10, timeWindowInSeconds = 60, maxRetries = 0)
public void processApiRequest() {
// Process API request ...
}
}
Here's an example of rate limiting based on a custom client identifier:
@Named
@RequestScoped
public class ApiController {
@RateLimit(clientId = "FooAPI", maxRequestsPerTimeWindow = 5, timeWindowInSeconds = 30, maxRetries = 1)
public void processFooAPIRequest() {
// Process Foo API request ...
}
}
When no clientId is specified, the rate limiter will automatically use the client IP address
from the current HttpServletRequest. If no HTTP request is available in the current context,
you must explicitly provide a clientId, otherwise an IllegalArgumentException will be thrown.
- Since:
- 5.0
- Author:
- Bauke Scholtz
- See Also:
-
Optional Element Summary
Optional ElementsModifier and TypeOptional ElementDescription(Optional) The client identifier to check, whether client IP, user ID, API key, etc.int(Optional) The maximum number of requests allowed within the time window.int(Optional) The maximum number of retries when rate limit is exceeded.long(Optional) The time window duration in seconds. -
Field Summary
FieldsModifier and TypeFieldDescriptionstatic final intstatic final intstatic final int
-
Field Details
-
DEFAULT_MAX_REQUESTS_PER_TIME_WINDOW
static final int DEFAULT_MAX_REQUESTS_PER_TIME_WINDOW- See Also:
-
DEFAULT_TIME_WINDOW_IN_SECONDS
static final int DEFAULT_TIME_WINDOW_IN_SECONDS- See Also:
-
DEFAULT_MAX_RETRIES
static final int DEFAULT_MAX_RETRIES- See Also:
-
-
Element Details
-
clientId
String clientId(Optional) The client identifier to check, whether client IP, user ID, API key, etc. Defaults to client IP address associated with the currentHttpServletRequest.Note thus that when you cannot guarantee that a
HttpServletRequestis available in the context of the annotated method, then you'll definitely need to explicitly provide a client ID, otherwise theRateLimitInterceptorwill throw anIllegalArgumentException.- Returns:
- The client identifier to check, whether client IP, user ID, API key, etc.
- Default:
- ""
-
maxRequestsPerTimeWindow
int maxRequestsPerTimeWindow(Optional) The maximum number of requests allowed within the time window. Defaults to 1.- Returns:
- The maximum number of requests allowed within the time window.
- Default:
- 1
-
timeWindowInSeconds
long timeWindowInSeconds(Optional) The time window duration in seconds. Defaults to 1.- Returns:
- The time window duration in seconds.
- Default:
- 1L
-
maxRetries
int maxRetries(Optional) The maximum number of retries when rate limit is exceeded. Defaults to 0 (no retries - fail immediately). Set to a positive value to enable automatic retries with calculated delays.- Returns:
- The maximum number of retries.
- Default:
- 0
-