← All articles
Backend1 min read

Database Caching with the Spring Cache Abstraction

Repeated database reads are the easiest performance win to claw back. Spring's cache abstraction lets you add caching declaratively without touching query code.

S

Swapnika Voora

Author

If a query returns the same result thousands of times between writes, you are paying for the database round trip every time. Spring's cache abstraction lets you memoize method results with annotations, keeping your query code untouched.

Turn caching on

Enable caching and register a cache manager. For local caches, Caffeine is a strong default with good eviction policies.

CacheConfig.java
@Configuration
@EnableCaching
public class CacheConfig {
 
    @Bean
    public CacheManager cacheManager() {
        CaffeineCacheManager manager = new CaffeineCacheManager("products");
        manager.setCaffeine(Caffeine.newBuilder()
            .maximumSize(10_000)
            .expireAfterWrite(Duration.ofMinutes(10)));
        return manager;
    }
}

Cache reads, evict on writes

@Cacheable stores the return value keyed by the method arguments. @CacheEvict clears entries when the underlying data changes so readers never see stale rows.

ProductService.java
@Service
public class ProductService {
 
    @Cacheable(value = "products", key = "#id")
    public Product findById(Long id) {
        return repository.findById(id).orElseThrow();
    }
 
    @CacheEvict(value = "products", key = "#product.id")
    public Product update(Product product) {
        return repository.save(product);
    }
}

Avoid the stampede

When a hot key expires, many threads can hit the database at once. Set sync = true so only one thread recomputes the value while others wait.

sync.java
@Cacheable(value = "products", key = "#id", sync = true)
public Product findById(Long id) {
    return repository.findById(id).orElseThrow();
}

Takeaways

  • Cache expensive, read-heavy queries — not everything.
  • Evict on writes to keep the cache consistent with the database.
  • Use sync = true to prevent cache stampedes on hot keys.

Start local with Caffeine; move to a distributed cache like Redis once you run more than one instance.

#java#spring-boot#caching#performance

More in Backend