LimiterX is a powerful yet simple rate-limiting library for Java and Spring Boot. It supports both fixed window and sliding window strategies and comes with a Spring Boot starter for easy integration.
Include the dependency in your pom.xml:
<dependency>
<groupId>io.github.d4rckh</groupId>
<artifactId>limiterx-spring-boot-starter</artifactId>
<version>0.0.4</version>
</dependency>Simply annotate any @Configuration class:
@Configuration
@EnableLimiterX
public class AppConfig { }Limits access to a method for all requests, regardless of the client:
@GetMapping
@RateLimited(
maximumRequests = 2,
windowSize = 10, // seconds
blockFor = 1000 // optional: block duration in seconds
)
public String hello() {
return "Hello!";
}Uses
X-Forwarded-Forif available; otherwise, falls back to the client's remote address:
@GetMapping
@RateLimited(
key = IPExtractor.class,
maximumRequests = 2,
windowSize = 10
)
public String hello() {
return "Hello!";
}Restricts access based on the authenticated user's username (requires Spring Security):
@GetMapping
@RateLimited(
key = UsernameExtractor.class,
maximumRequests = 2,
windowSize = 10
)
public String hello() {
return "Hello!";
}Key extractors define how requests are grouped for rate limiting:
- NoopExtractor (default) – No key extraction; all requests share the same limit.
- IPExtractor – Uses the client’s IP address.
- UsernameExtractor – Uses the authenticated username from Spring Security.
Make a key using a Spring expression, only the beans implementing KeyExtractor are loaded using their class name.
This will combine the UsernameExtractor with the IPExtractor. Warning: if the user is not authenticated, the key will only be formed using the IP
@GetMapping
@RateLimited(
keyExpression = "{#UsernameExtractor.extract(), #IPExtractor.extract()}",
maximumRequests = 2,
windowSize = 10
)
public String hello() {
return "Hello!";
}When the extracted key is null, you can choose how LimiterX handles it:
- LIMIT – Uses a shared key for all such requests.
- FORBID – Blocks requests with
nullkeys. - AUTO – Uses
LIMITforNoopExtractor, otherwiseFORBID.
By default, LimiterX stores rate-limiting data in Redis. To switch to in-memory storage, add this property:
limiterx.storage=memoryNeed custom rate-limiting logic? Implement KeyExtractor in your own class:
You can use these in the keyExpression parameter!
@Component
public class IPExtractor implements KeyExtractor {
private final ObjectFactory<HttpServletRequest> requestFactory;
@Autowired
public IPExtractor(ObjectFactory<HttpServletRequest> requestFactory) {
this.requestFactory = requestFactory;
}
public String extract() {
String xForwardedForHeader = requestFactory.getObject().getHeader("X-Forwarded-For");
return xForwardedForHeader == null ? httpRequest.getRemoteAddr() : xForwardedForHeader;
}
}@Component
public class MyExtractor implements KeyExtractor {
private final ObjectFactory<HttpServletRequest> requestFactory;
@Autowired
public IPExtractor(ObjectFactory<HttpServletRequest> requestFactory) {
this.requestFactory = requestFactory;
}
public String extract(String headerName) {
return requestFactory.getHeader(headerName);
}
}
@GetMapping
@RateLimited(
keyExpression = "#MyExtractor.extract('something')",
maximumRequests = 2,
windowSize = 10
)
public String hello() {
return "Hello!";
}LimiterX is open-source and licensed under the MIT License.
Enjoy rate limiting with LimiterX! 🚀