Spring Boot Cache Abstraction
Overview
Spring Boot ships with a cache abstraction that wraps expensive service calls
behind annotation-driven caches. This abstraction supports multiple cache
providers (ConcurrentMap, Caffeine, Redis, Ehcache, JCache) without changing
business code. The skill provides a concise workflow for enabling caching,
managing cache lifecycles, and validating behavior in Spring Boot 3.5+ services.
When to Use
- Add
@Cacheable, @CachePut, or @CacheEvict to Spring Boot service methods.
- Configure Caffeine, Redis, or JCache cache managers for Spring Boot.
- Diagnose cache invalidation, eviction scheduling, or cache key issues.
- Expose cache management endpoints or scheduled eviction routines.
Use trigger phrases such as "implement service caching", "configure
CaffeineCacheManager", "evict caches on update", or "test Spring cache
behavior" to load this skill.
Prerequisites
- Java 17+ project based on Spring Boot 3.5.x (records encouraged for DTOs).
- Dependency
spring-boot-starter-cache; add provider-specific starters as
needed (spring-boot-starter-data-redis, caffeine, ehcache, etc.).
- Constructor-injected services that expose deterministic method signatures.
- Observability stack (Actuator, Micrometer) when operating caches in
production.
Quick Start
Add dependencies
<!-- Maven -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<dependency> <!-- Optional: Caffeine -->
<groupId>com.github.ben-manes.caffeine</groupId>
<artifactId>caffeine</artifactId>
</dependency>
implementation "org.springframework.boot:spring-boot-starter-cache"
implementation "com.github.ben-manes.caffeine:caffeine"
Enable caching
@Configuration
@EnableCaching
class CacheConfig {
@Bean
CacheManager cacheManager() {
return new CaffeineCacheManager("users", "orders");
}
}
Annotate service methods
@Service
@CacheConfig(cacheNames = "users")
class UserService {
@Cacheable(key = "#id", unless = "#result == null")
User findUser(Long id) { ... }
@CachePut(key = "#user.id")
User refreshUser(User user) { ... }
@CacheEvict(key = "#id", beforeInvocation = false)
void deleteUser(Long id) { ... }
}
Verify behavior
- Run focused unit tests that call cached methods twice and assert repository
invocations.
- Inspect Actuator
cache endpoint (if enabled) for hit/miss counters.
Implementation Workflow
1. Define Cache Strategy
- Map hot-path read operations to
@Cacheable.
- Use
@CachePut on write paths that must refresh cache entries.
- Apply
@CacheEvict (allEntries = true when invalidating derived caches).
- Combine operations with
@Caching to keep multi-cache updates consistent.
2. Shape Cache Keys and Conditions
- Generate deterministic keys via SpEL (e.g.
key = "#user.id").
- Guard caching with
condition = "#price > 0" for selective caching.
- Prevent null or stale values with
unless = "#result == null".
- Synchronize concurrent updates via
sync = true when needed.
3. Manage Providers and TTLs
- Configure provider-specific options:
- Caffeine spec:
spring.cache.caffeine.spec=maximumSize=500,expireAfterWrite=10m
- Redis TTL:
spring.cache.redis.time-to-live=600000
- Ehcache XML: define
ttl and heap/off-heap resources.
- Expose cache names via
spring.cache.cache-names=users,orders,catalog.
- Avoid on-demand cache name creation in production unless metrics cover usage.
4. Operate and Observe Caches
- Surface cache maintenance via a dedicated
CacheManagementService with
programmatic cacheManager.getCache(name) access.
- Schedule periodic eviction for time-bound caches using
@Scheduled.
- Wire Actuator
cache endpoint and Micrometer meters to track hit ratio,
eviction count, and size.
5. Test and Validate
- Prefer slice or unit tests with Mockito/SpyBean to ensure method invocation
counts.
- Add integration tests with Testcontainers for Redis/Ehcache when using
external providers.
- Validate concurrency behavior under load (e.g.
sync = true scenarios).
Advanced Options
- Integrate JCache annotations when interoperating with providers that favor
JSR-107 (
@CacheResult, @CacheRemove). Avoid mixing with Spring annotations
on the same method.
- Cache reactive return types (
Mono, Flux) or CompletableFuture values.
Spring stores resolved values and resubscribes on hits; consider TTL alignment
with publisher semantics.
- Apply HTTP caching headers using
CacheControl when exposing cached responses
via REST.
Examples
- Load
references/cache-examples.md for
progressive scenarios (basic product cache, conditional caching, multilevel
eviction, Redis integration).
- Load
references/cache-core-reference.md
for annotation matrices, configuration tables, and property samples.
References
references/spring-framework-cache-docs.md:
curated excerpts from the Spring Framework Reference Guide (official).
references/spring-cache-doc-snippet.md:
narrative overview extracted from Spring documentation.
references/cache-core-reference.md:
annotation parameters, dependency matrices, property catalogs.
references/cache-examples.md:
end-to-end examples with tests.
Best Practices
- Prefer constructor injection and immutable DTOs for cache entries.
- Separate cache names per aggregate (
users, orders) to simplify eviction.
- Log cache hits/misses only at debug to avoid noise; push metrics via Micrometer.
- Tune TTLs based on data staleness tolerance; document rationale in code.
- Guard caches that store PII or credentials with encryption or avoid caching.
- Align cache eviction with transactional boundaries to prevent dirty reads.
Constraints and Warnings
- Avoid caching mutable entities that depend on open persistence contexts.
- Do not mix Spring cache annotations with JCache annotations on the same
method.
- Ensure multi-level caches (e.g. Caffeine + Redis) maintain consistency; prefer
publish/subscribe invalidation channels.
- Validate serialization compatibility when caching across service instances.
- Monitor memory footprint to prevent OOM when using in-memory stores.
Related Skills
1---2name: spring-boot-cache3description: Instruction set for enabling and operating the Spring Cache abstraction in Spring Boot when implementing application-level caching for performance-sensitive workloads.4---56# Spring Boot Cache Abstraction78## Overview910Spring Boot ships with a cache abstraction that wraps expensive service calls11behind annotation-driven caches. This abstraction supports multiple cache12providers (ConcurrentMap, Caffeine, Redis, Ehcache, JCache) without changing13business code. The skill provides a concise workflow for enabling caching,14managing cache lifecycles, and validating behavior in Spring Boot 3.5+ services.1516## When to Use1718- Add `@Cacheable`, `@CachePut`, or `@CacheEvict` to Spring Boot service methods.19- Configure Caffeine, Redis, or JCache cache managers for Spring Boot.20- Diagnose cache invalidation, eviction scheduling, or cache key issues.21- Expose cache management endpoints or scheduled eviction routines.2223Use trigger phrases such as **"implement service caching"**, **"configure24CaffeineCacheManager"**, **"evict caches on update"**, or **"test Spring cache25behavior"** to load this skill.2627## Prerequisites2829- Java 17+ project based on Spring Boot 3.5.x (records encouraged for DTOs).30- Dependency `spring-boot-starter-cache`; add provider-specific starters as31 needed (`spring-boot-starter-data-redis`, `caffeine`, `ehcache`, etc.).32- Constructor-injected services that expose deterministic method signatures.33- Observability stack (Actuator, Micrometer) when operating caches in34 production.3536## Quick Start37381. **Add dependencies**3940 ```xml41 <!-- Maven -->42 <dependency>43 <groupId>org.springframework.boot</groupId>44 <artifactId>spring-boot-starter-cache</artifactId>45 </dependency>46 <dependency> <!-- Optional: Caffeine -->47 <groupId>com.github.ben-manes.caffeine</groupId>48 <artifactId>caffeine</artifactId>49 </dependency>50 ```5152 ```gradle53 implementation "org.springframework.boot:spring-boot-starter-cache"54 implementation "com.github.ben-manes.caffeine:caffeine"55 ```56572. **Enable caching**5859 ```java60 @Configuration61 @EnableCaching62 class CacheConfig {63 @Bean64 CacheManager cacheManager() {65 return new CaffeineCacheManager("users", "orders");66 }67 }68 ```69703. **Annotate service methods**7172 ```java73 @Service74 @CacheConfig(cacheNames = "users")75 class UserService {7677 @Cacheable(key = "#id", unless = "#result == null")78 User findUser(Long id) { ... }7980 @CachePut(key = "#user.id")81 User refreshUser(User user) { ... }8283 @CacheEvict(key = "#id", beforeInvocation = false)84 void deleteUser(Long id) { ... }85 }86 ```87884. **Verify behavior**89 - Run focused unit tests that call cached methods twice and assert repository90 invocations.91 - Inspect Actuator `cache` endpoint (if enabled) for hit/miss counters.9293## Implementation Workflow9495### 1. Define Cache Strategy9697- Map hot-path read operations to `@Cacheable`.98- Use `@CachePut` on write paths that must refresh cache entries.99- Apply `@CacheEvict` (`allEntries = true` when invalidating derived caches).100- Combine operations with `@Caching` to keep multi-cache updates consistent.101102### 2. Shape Cache Keys and Conditions103104- Generate deterministic keys via SpEL (e.g. `key = "#user.id"`).105- Guard caching with `condition = "#price > 0"` for selective caching.106- Prevent null or stale values with `unless = "#result == null"`.107- Synchronize concurrent updates via `sync = true` when needed.108109### 3. Manage Providers and TTLs110111- Configure provider-specific options:112 - Caffeine spec: `spring.cache.caffeine.spec=maximumSize=500,expireAfterWrite=10m`113 - Redis TTL: `spring.cache.redis.time-to-live=600000`114 - Ehcache XML: define `ttl` and heap/off-heap resources.115- Expose cache names via `spring.cache.cache-names=users,orders,catalog`.116- Avoid on-demand cache name creation in production unless metrics cover usage.117118### 4. Operate and Observe Caches119120- Surface cache maintenance via a dedicated `CacheManagementService` with121 programmatic `cacheManager.getCache(name)` access.122- Schedule periodic eviction for time-bound caches using `@Scheduled`.123- Wire Actuator `cache` endpoint and Micrometer meters to track hit ratio,124 eviction count, and size.125126### 5. Test and Validate127128- Prefer slice or unit tests with Mockito/SpyBean to ensure method invocation129 counts.130- Add integration tests with Testcontainers for Redis/Ehcache when using131 external providers.132- Validate concurrency behavior under load (e.g. `sync = true` scenarios).133134## Advanced Options135136- Integrate JCache annotations when interoperating with providers that favor137 JSR-107 (`@CacheResult`, `@CacheRemove`). Avoid mixing with Spring annotations138 on the same method.139- Cache reactive return types (`Mono`, `Flux`) or `CompletableFuture` values.140 Spring stores resolved values and resubscribes on hits; consider TTL alignment141 with publisher semantics.142- Apply HTTP caching headers using `CacheControl` when exposing cached responses143 via REST.144145## Examples146147- Load [`references/cache-examples.md`](references/cache-examples.md) for148 progressive scenarios (basic product cache, conditional caching, multilevel149 eviction, Redis integration).150- Load [`references/cache-core-reference.md`](references/cache-core-reference.md)151 for annotation matrices, configuration tables, and property samples.152153## References154155- [`references/spring-framework-cache-docs.md`](references/spring-framework-cache-docs.md):156 curated excerpts from the Spring Framework Reference Guide (official).157- [`references/spring-cache-doc-snippet.md`](references/spring-cache-doc-snippet.md):158 narrative overview extracted from Spring documentation.159- [`references/cache-core-reference.md`](references/cache-core-reference.md):160 annotation parameters, dependency matrices, property catalogs.161- [`references/cache-examples.md`](references/cache-examples.md):162 end-to-end examples with tests.163164## Best Practices165166- Prefer constructor injection and immutable DTOs for cache entries.167- Separate cache names per aggregate (`users`, `orders`) to simplify eviction.168- Log cache hits/misses only at debug to avoid noise; push metrics via Micrometer.169- Tune TTLs based on data staleness tolerance; document rationale in code.170- Guard caches that store PII or credentials with encryption or avoid caching.171- Align cache eviction with transactional boundaries to prevent dirty reads.172173## Constraints and Warnings174175- Avoid caching mutable entities that depend on open persistence contexts.176- Do not mix Spring cache annotations with JCache annotations on the same177 method.178- Ensure multi-level caches (e.g. Caffeine + Redis) maintain consistency; prefer179 publish/subscribe invalidation channels.180- Validate serialization compatibility when caching across service instances.181- Monitor memory footprint to prevent OOM when using in-memory stores.182183## Related Skills184185- [`skills/spring-boot/spring-boot-rest-api-standards`](../spring-boot-rest-api-standards/SKILL.md)186- [`skills/spring-boot/spring-boot-test-patterns`](../spring-boot-test-patterns/SKILL.md)187- [`skills/junit-test/unit-test-caching`](../../junit-test/unit-test-caching/SKILL.md)