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.
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.
Architect's Tech Stack
Java backend, microservices, distributed systems, containerized programming, and more.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.