Quarkus Bucket4j

Bucket4J is a Java rate-limiting library based on the token-bucket algorithm. Bucket4j is a thread-safe library that can be used in either a standalone JVM application, or a clustered environment. It also supports in-memory or distributed caching via the JCache (JSR107) specification. This extension allow you to control the request rate sent to your application by using a dead simple API.

Installation

If you want to use this extension, you need to add the io.quarkiverse.bucket4j:quarkus-bucket4j extension first to your build file.

For instance, with Maven, add the following dependency to your POM file:

<dependency>
    <groupId>io.quarkiverse.bucket4j</groupId>
    <artifactId>quarkus-bucket4j</artifactId>
    <version>1.0.4</version>
</dependency>

Getting Started

Throttling a Method

Annotate the method that need to be throttled with @RateLimited

@ApplicationScoped
public static class RateLimitedMethods {

    @RateLimited(bucket = "group1")
    public String limited() {
        return "LIMITED";
    }

}

You can also annotate a class, in that case all methods in the class are throttled

@ApplicationScoped
@RateLimited(bucket = "group1")
public static class RateLimitedMethods {

    public String limited() {
        return "LIMITED";
    }

}

And add a limit group using the same bucket id in the configuration:

# burst protection
quarkus.rate-limiter.buckets.group1.limits[0].permitted-uses: 10
quarkus.rate-limiter.buckets.group1.limits[0].period: 1S
# fair use
quarkus.rate-limiter.buckets.group1.limits[1].permitted-uses: 100
quarkus.rate-limiter.buckets.group1.limits[1].period: 5M

or with yaml:

quarkus:
  rate-limiter:
    buckets:
      group1:
        limits:
          - permitted-uses: 10
            period: 1S
          - permitted-uses: 100
            period: 5M

The bucket can contain multiple limits that will all be enforced.

Bucket Sharing

By default, if multiple methods share the same bucket id, each method has its own quota. You can change this behaviour by enabling the shared option in the configuration.

# burst protection
quarkus.rate-limiter.buckets.group1.shared: true
quarkus.rate-limiter.buckets.group1.limits[0].permitted-uses: 10
quarkus.rate-limiter.buckets.group1.limits[0].period: 1S

Population Segmentation

If you want to perform the throttling per user, simply specify an IdentityKeyResolver either in the bucket config or in the RateLimited annotation. If a value is specified in the annotation, it will take precedence over the config. The default one is the ConstantResolver, which will cause the segmentation to be disabled.

@ApplicationScoped
public static class RateLimitedMethods {

    @RateLimited(bucket = "group1", identityResolver = IpResolver.class)
    public String limitedByIp() {
        return "LIMITED";
    }
}

IpResolver is provided out of the box. if you want a more complex segmentation, you can implement your own resolver. A custom resolver must be a valid CDI Bean.

Extension Configuration Reference

Configuration property fixed at build time - All other configuration properties are overridable at runtime

Configuration property

Type

Default

rate limiter will be completely disabled if false

Environment variable: QUARKUS_RATE_LIMITER_ENABLED

boolean

true

Maximum number of entries in the underlying cache

Environment variable: QUARKUS_RATE_LIMITER_MAX_SIZE

int

1000

Duration during which the bucket is kept after last refill if untouched

Environment variable: QUARKUS_RATE_LIMITER_KEEP_AFTER_REFILL

Duration

1H

Identity resolver allow to segment the population. Each resolved identity key will have its own quota. this must be a valid CDI bean implementing IdentityResolver.

Environment variable: QUARKUS_RATE_LIMITER_BUCKETS__BUCKET_ID__IDENTITY_RESOLVER

string

io.quarkiverse.bucket4j.runtime.resolver.ConstantResolver

limits enforced for this bucket

Environment variable: QUARKUS_RATE_LIMITER_BUCKETS__BUCKET_ID__LIMITS

list of Limit

required

If true, permitted uses are shared for all methods using the same bucket id. If false, each method has its own quota.

Environment variable: QUARKUS_RATE_LIMITER_BUCKETS__BUCKET_ID__SHARED

boolean

false