Backend Development 22 min read

Caffeine Cache in Spring Boot: Algorithms, Configuration, and Practical Usage

This article introduces Caffeine Cache as a high‑performance local caching solution that improves on Guava Cache by using the W‑TinyLFU eviction algorithm, explains its core concepts, demonstrates manual, synchronous, and asynchronous loading strategies, details eviction policies, and provides step‑by‑step integration and configuration examples for Spring Boot applications.

Architect's Tech Stack
Architect's Tech Stack
Architect's Tech Stack
Caffeine Cache in Spring Boot: Algorithms, Configuration, and Practical Usage

Caffeine Cache is a modern Java caching library that builds upon the ideas of Guava Cache while offering superior eviction strategies, notably the W‑TinyLFU algorithm, which combines LFU and LRU to achieve near‑optimal hit rates.

1. Algorithm Advantages – W‑TinyLFU

Traditional eviction policies such as FIFO, LRU, and LFU each have drawbacks; FIFO suffers low hit rates, LRU can evict hot items under burst traffic, and LFU struggles with changing access patterns. W‑TinyLFU addresses these issues by using a Count‑Min Sketch with a sliding window to track recent frequencies, allowing the cache to adapt to both steady and bursty workloads.

2. Usage in Java

Caffeine provides three loading strategies:

Manual loading : Use cache.get(key, k -> loadFunction(k)) to compute a value when the key is absent.

Synchronous loading : Build a LoadingCache with a CacheLoader that defines a load method.

Asynchronous loading : Build an AsyncLoadingCache with an AsyncCacheLoader returning a CompletableFuture .

Example of manual loading:

Cache
cache = Caffeine.newBuilder()
    .expireAfterWrite(1, TimeUnit.SECONDS)
    .expireAfterAccess(1, TimeUnit.SECONDS)
    .maximumSize(10)
    .build();
Object value = cache.get(key, k -> computeValue(k));
cache.put("hello", value);
Object present = cache.getIfPresent(key);
cache.invalidate(key);

Example of synchronous loading:

LoadingCache
cache = Caffeine.newBuilder()
    .maximumSize(100)
    .expireAfterWrite(1, TimeUnit.MINUTES)
    .build(k -> loadFromDatabase(k));
Object v = cache.get(key);

Example of asynchronous loading:

AsyncLoadingCache
cache = Caffeine.newBuilder()
    .maximumSize(100)
    .expireAfterWrite(1, TimeUnit.MINUTES)
    .buildAsync(k -> CompletableFuture.supplyAsync(() -> loadAsync(k)));
CompletableFuture
future = cache.get(key);

3. Eviction Policies

Caffeine supports size‑based, time‑based, and reference‑based eviction:

Size‑based: maximumSize or maximumWeight (mutually exclusive).

Time‑based: expireAfterAccess , expireAfterWrite , or a custom Expiry implementation.

Reference‑based: weakKeys , weakValues , softValues (soft and weak values cannot be used together).

Removal listeners can be registered to react when entries are evicted:

Cache
cache = Caffeine.newBuilder()
    .removalListener((key, value, cause) ->
        System.out.printf("Key %s was removed (%s)%n", key, cause))
    .build();

4. Integration with Spring Boot

Since Spring Boot 2.x, Caffeine replaces Guava as the default local cache. To use it:

Add the dependencies: <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-cache</artifactId> </dependency> <dependency> <groupId>com.github.ben-manes.caffeine</groupId> <artifactId>caffeine</artifactId> <version>2.6.2</version> </dependency>

Enable caching with @EnableCaching on a configuration class.

Configure caches via application.properties or application.yml , e.g.: spring.cache.cache-names=cache1 spring.cache.caffeine.spec=initialCapacity=50,maximumSize=500,expireAfterWrite=10s

Optionally define a CacheLoader bean when using refreshAfterWrite .

Programmatic cache creation using CaffeineCache and SimpleCacheManager for multiple caches with different TTLs and sizes.

5. Cache Annotations

Spring provides several annotations to work with caches without writing explicit code:

@Cacheable : Checks the cache before method execution; if absent, executes the method and stores the result.

@CachePut : Always executes the method and updates the cache with the result.

@CacheEvict : Removes entries from the cache.

@Caching : Combines multiple cache annotations on a single method.

@CacheConfig : Shares common cache settings at the class level.

SpEL expressions can be used to define cache keys, conditions, and other attributes, with context variables such as #root.methodName , #args , and #result .

6. Summary

Caffeine offers a flexible, high‑performance caching solution for Java applications, especially when integrated with Spring Boot. Its advanced eviction algorithm, rich configuration options, and seamless annotation support make it suitable for a wide range of backend scenarios.

Spring BootCaffeine CacheCache Evictionw-tinylfuJava Caching
Architect's Tech Stack
Written by

Architect's Tech Stack

Java backend, microservices, distributed systems, containerized programming, and more.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.