Skip to content

Advanced Usage

frosxt edited this page Jan 19, 2026 · 1 revision

Advanced Usage

Asynchronous Acquisition

BucketGuard supports non-blocking, asynchronous token acquisition. This is useful for reactive applications or when you want to queue a request without blocking a thread.

Note: To support delayed retries (waiting for tokens to regenerate), you must provide a ScheduledExecutorService.

ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();

CompletableFuture<Permit> future = limiter.acquireAsync(scheduler).toCompletableFuture();

future.thenAccept(permit -> {
    System.out.println("Token acquired!");
});

Burst Control

Standard token buckets allow "bursts". If a bucket sits idle, it accumulates tokens up to its capacity. This allows a client to perform a quick burst of actions after a period of inactivity.

If you prefer to strictly space out requests (smoothing), disable bursts.

TokenBucketSpec.builder()
    .allowBurst(false) // Traffic is smoothed
    .build();

When allowBurst is false:

  1. The bucket never holds more than 1 token effectively available for immediate burst (internally handled via specialized math).
  2. Requests are forced to wait for the refill interval.
  3. Attempts to acquire multiple tokens at once (tryAcquire(5)) will fail or block until they can be dripped out one by one.

Strict Math

For applications handling critical resources or running for extremely long durations, integer overflow in token calculations is a theoretical risk.

Enable strictMath to force ArithmeticException on any overflow, preventing silent failures.

TokenBucketSpec.builder()
    .strictMath(true)
    .build();

Contention Stripping

In extremely high-throughput scenarios (e.g., millions of checks per second), a single AtomicLong can become a contention point due to failed CAS (Compare-And-Swap) operations.

BucketGuard supports Striped buckets. This splits the capacity across multiple internal buckets.

TokenBucketSpec.builder()
    .contentionStrategy(ContentionStrategy.STRIPED)
    .build();

Trade-offs:

  • Pros: Significantly higher throughput under massive contention.
  • Cons: Slightly less strict adherence to the exact limit (small variations can occur due to load balancing across stripes).

Clone this wiki locally