Using Caffeine Cache in Spring Boot: Features, Configuration, and Code Examples

This article introduces Caffeine Cache as a modern local caching solution, explains its W‑TinyLFU algorithm advantages over Guava, demonstrates various loading and eviction strategies, and provides detailed Spring Boot integration examples with Maven dependencies, configuration, annotations, and custom bean setups.

Top Architect
Top Architect
Top Architect
Using Caffeine Cache in Spring Boot: Features, Configuration, and Code Examples

Guava Cache provides basic thread‑safe caching with simple LRU eviction, but Caffeine Cache builds on its ideas and adds a more advanced eviction algorithm called W‑TinyLFU, which combines LFU and LRU to achieve near‑optimal hit rates.

1. Algorithm Advantages – W‑TinyLFU

Caffeine improves on FIFO, LRU, and LFU by using a Count‑Min Sketch to record recent access frequencies and a sliding‑window reset to decay old data, allowing it to handle both steady‑state and bursty workloads efficiently.

2. Usage in Java

The library is available from Maven Central:

<dependency>
  <groupId>com.github.ben-manes.caffeine</groupId>
  <artifactId>caffeine</artifactId>
  <version>2.6.2</version>
</dependency>

2.1 Manual Loading

public Object manualOperator(String key) {
    Cache<String, Object> cache = Caffeine.newBuilder()
        .expireAfterWrite(1, TimeUnit.SECONDS)
        .expireAfterAccess(1, TimeUnit.SECONDS)
        .maximumSize(10)
        .build();
    Object value = cache.get(key, t -> setValue(key).apply(key));
    cache.put("hello", value);
    Object ifPresent = cache.getIfPresent(key);
    cache.invalidate(key);
    return value;
}

public Function<String, Object> setValue(String key) {
    return t -> key + "value";
}

2.2 Synchronous Loading

public Object syncOperator(String key) {
    LoadingCache<String, Object> cache = Caffeine.newBuilder()
        .maximumSize(100)
        .expireAfterWrite(1, TimeUnit.MINUTES)
        .build(k -> setValue(key).apply(key));
    return cache.get(key);
}

2.3 Asynchronous Loading

public Object asyncOperator(String key) {
    AsyncLoadingCache<String, Object> cache = Caffeine.newBuilder()
        .maximumSize(100)
        .expireAfterWrite(1, TimeUnit.MINUTES)
        .buildAsync(k -> setAsyncValue(key).get());
    return cache.get(key);
}

public CompletableFuture<Object> setAsyncValue(String key) {
    return CompletableFuture.supplyAsync(() -> key + "value");
}

3. Eviction Strategies

Caffeine supports three families of eviction policies:

Size‑based : .maximumSize() or .maximumWeight() with a custom .weigher().

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

Reference‑based : .weakKeys(), .weakValues(), .softValues() (note that AsyncLoadingCache cannot use weak/soft references).

Examples:

// Size‑based eviction
LoadingCache<String, Object> cache = Caffeine.newBuilder()
    .maximumSize(10000)
    .build(key -> function(key));

// Time‑based eviction
LoadingCache<String, Object> cache = Caffeine.newBuilder()
    .expireAfterAccess(5, TimeUnit.MINUTES)
    .build(key -> function(key));

3.1 Removal Listener

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

3.2 CacheWriter

LoadingCache<String, Object> cache = Caffeine.newBuilder()
    .writer(new CacheWriter<String, Object>() {
        @Override public void write(String key, Object value) { /* write to external store */ }
        @Override public void delete(String key, Object value, RemovalCause cause) { /* delete from store */ }
    })
    .build(key -> function(key));

4. Statistics

Cache<String, Object> cache = Caffeine.newBuilder()
    .maximumSize(10_000)
    .recordStats()
    .build();
CacheStats stats = cache.stats(); // hitRate(), evictionCount(), averageLoadPenalty(), …

5. Spring Boot Integration

Spring Boot 2.x replaces Guava with Caffeine as the default local cache. Add the following 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 the main application class.

5.1 Property‑Based Configuration

# application.properties
spring.cache.cache-names=cache1
spring.cache.caffeine.spec=initialCapacity=50,maximumSize=500,expireAfterWrite=10s

Or YAML:

spring:
  cache:
    type: caffeine
    cache-names:
      - userCache
    caffeine:
      spec: maximumSize=1024,refreshAfterWrite=60s

If refreshAfterWrite is used, a CacheLoader<Object, Object> bean must be defined.

5.2 Bean‑Based Cache Manager

@Configuration
public class CacheConfig {
    @Bean
    public CacheLoader<String, Object> cacheLoader() {
        return new CacheLoader<String, Object>() {
            @Override public Object load(String key) { return null; }
            @Override public Object reload(String key, Object oldValue) { return oldValue; }
        };
    }

    @Bean @Primary
    public CacheManager caffeineCacheManager() {
        SimpleCacheManager manager = new SimpleCacheManager();
        List<CaffeineCache> caches = new ArrayList<>();
        caches.add(new CaffeineCache("userCache",
            Caffeine.newBuilder()
                .recordStats()
                .expireAfterWrite(60, TimeUnit.SECONDS)
                .maximumSize(10000)
                .build()));
        manager.setCaches(caches);
        return manager;
    }
}

5.3 Cache Configuration Options

Common Caffeine spec keys include initialCapacity, maximumSize, maximumWeight, expireAfterAccess, expireAfterWrite, refreshAfterWrite, weakKeys, weakValues, softValues, and recordStats. Note that maximumSize and maximumWeight are mutually exclusive, as are weakValues and softValues.

6. Annotation‑Based Cache Operations

Spring Cache annotations simplify cache usage: @Cacheable – reads from cache or executes the method and stores the result. @CachePut – always executes the method and updates the cache. @CacheEvict – removes entries from the cache. @Caching – groups multiple cache annotations on a single method. @CacheConfig – defines common cache settings at the class level.

@Service
public class UserCacheService {
    @Cacheable(value = "userCache", key = "#id", sync = true)
    public void getUser(long id) { /* query DB */ }

    @CachePut(value = "userCache", key = "#user.id")
    public void saveUser(User user) { /* persist */ }

    @CacheEvict(value = "userCache", key = "#user.id")
    public void delUser(User user) { /* delete */ }
}

SpEL can be used for keys (e.g., #id, #p0, or full expressions). The root object and method parameters are available for constructing cache keys.

7. Summary

Caffeine Cache offers a high‑performance, feature‑rich alternative to Guava Cache, with sophisticated eviction via W‑TinyLFU, flexible size‑, time‑, and reference‑based policies, statistics, removal listeners, and seamless Spring Boot integration through properties, YAML, or programmatic bean configuration. Using Spring’s caching annotations further simplifies cache management in Java backend applications.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

javaPerformanceCacheCaffeineSpringBoot
Top Architect
Written by

Top Architect

Top Architect focuses on sharing practical architecture knowledge, covering enterprise, system, website, large‑scale distributed, and high‑availability architectures, plus architecture adjustments using internet technologies. We welcome idea‑driven, sharing‑oriented architects to exchange and learn together.

0 followers
Reader feedback

How this landed with the community

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.