A local cache is fast but isolated — each instance holds its own copy, and evictions on one node do not reach the others. Redis solves this by giving every instance a single shared cache with server-side expiry.
Wire up Redis as the cache manager
Add spring-boot-starter-data-redis and configure a RedisCacheManager. Setting
a default TTL means entries expire even if you forget to evict them.
@Configuration
@EnableCaching
public class RedisCacheConfig {
@Bean
public RedisCacheManager cacheManager(RedisConnectionFactory factory) {
RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
.entryTtl(Duration.ofMinutes(15))
.serializeValuesWith(SerializationPair.fromSerializer(
new GenericJackson2JsonRedisSerializer()));
return RedisCacheManager.builder(factory)
.cacheDefaults(config)
.build();
}
}The annotations don't change
The beauty of the cache abstraction is that switching backends is a config change. Your service code stays identical to a local cache setup.
@Service
public class CatalogService {
@Cacheable(value = "catalog", key = "#category")
public List<Product> byCategory(String category) {
return repository.findByCategory(category);
}
}Point Spring at your Redis
spring.data.redis.host=localhost
spring.data.redis.port=6379
spring.data.redis.timeout=2sTakeaways
- Redis turns caching from per-instance to cluster-wide.
- Always set a default TTL as a safety net against stale data.
- Use a JSON serializer so cached values stay human-readable and portable.
Watch your serialization format: changing a DTO shape can make old cached entries fail to deserialize, so version your keys when models evolve.