Spring Boot Pro Tip: Boost Performance with @Cacheable + Java 17
If your Spring Boot app is hitting the database too often and slowing down, you need caching! Using @Cacheable, you can reduce unnecessary queries, speed up responses, and improve scalability. Let’s explore how to cache efficiently and avoid common pitfalls. The Problem: Too Many Database Calls Imagine we have a user service fetching data from the database: @Service public class UserService { @Autowired private UserRepository userRepository; public User getUserById(Long id) { return userRepository.findById(id).orElseThrow(); } } Every time getUserById() is called, it hits the database. But do we really need to fetch the same user multiple times? The Solution: @Cacheable Spring Boot makes caching easy. Just add @EnableCaching in your main class: @SpringBootApplication @EnableCaching public class MyApplication { public static void main(String[] args) { SpringApplication.run(MyApplication.class, args); } } Then, modify your service to cache users: @Service public class UserService { @Autowired private UserRepository userRepository; @Cacheable("users") public User getUserById(Long id) { return userRepository.findById(id).orElseThrow(); } } Now, when getUserById(id) is called multiple times, it returns the cached result instead of querying the database again! Fine-Tuning the Cache By default, @Cacheable caches results forever. To control expiration, use Caffeine or Redis. Use Caffeine for In-Memory Caching (Fast & Lightweight) Add the dependency: com.github.ben-manes.caffeine caffeine 3.0.6 Then, configure the cache with TTL (Time-To-Live) settings: @Configuration public class CacheConfig { @Bean public CacheManager cacheManager() { return new CaffeineCacheManager("users"); } } This ensures cached users expire after a certain period, preventing stale data. Use Redis for Distributed Caching (Great for Microservices) For scalability, store cached data in Redis: Add Redis dependency: org.springframework.boot spring-boot-starter-data-redis Configure Redis in application.yml: spring: redis: host: localhost port: 6379 Use Redis as Cache Manager: @Configuration public class RedisConfig { @Bean public RedisCacheManager cacheManager(RedisConnectionFactory connectionFactory) { return RedisCacheManager.builder(connectionFactory).build(); } } Result: The cache is shared across multiple instances, perfect for cloud deployments! Common Cache Mistakes to Avoid Forgetting to update the cache when data changes Use @CachePut to update cache when saving new data @CachePut(value = "users", key = "#user.id") public User saveUser(User user) { return userRepository.save(user); } Caching large objects Cache only frequent, small, and non-sensitive data Not setting an expiration time Always define TTL to prevent outdated data issues

If your Spring Boot app is hitting the database too often and slowing down, you need caching! Using @Cacheable, you can reduce unnecessary queries, speed up responses, and improve scalability.
Let’s explore how to cache efficiently and avoid common pitfalls.
The Problem: Too Many Database Calls
Imagine we have a user service fetching data from the database:
@Service
public class UserService {
@Autowired private UserRepository userRepository;
public User getUserById(Long id) {
return userRepository.findById(id).orElseThrow();
}
}
Every time getUserById() is called, it hits the database. But do we really need to fetch the same user multiple times?
The Solution: @Cacheable
Spring Boot makes caching easy. Just add @EnableCaching in your main class:
@SpringBootApplication
@EnableCaching
public class MyApplication {
public static void main(String[] args) {
SpringApplication.run(MyApplication.class, args);
}
}
Then, modify your service to cache users:
@Service
public class UserService {
@Autowired private UserRepository userRepository;
@Cacheable("users")
public User getUserById(Long id) {
return userRepository.findById(id).orElseThrow();
}
}
Now, when getUserById(id) is called multiple times, it returns the cached result instead of querying the database again!
Fine-Tuning the Cache
By default, @Cacheable caches results forever. To control expiration, use Caffeine or Redis.
Use Caffeine for In-Memory Caching (Fast & Lightweight)
Add the dependency:
com.github.ben-manes.caffeine
caffeine
3.0.6
Then, configure the cache with TTL (Time-To-Live) settings:
@Configuration
public class CacheConfig {
@Bean
public CacheManager cacheManager() {
return new CaffeineCacheManager("users");
}
}
This ensures cached users expire after a certain period, preventing stale data.
Use Redis for Distributed Caching (Great for Microservices)
For scalability, store cached data in Redis:
Add Redis dependency:
org.springframework.boot
spring-boot-starter-data-redis
Configure Redis in application.yml:
spring:
redis:
host: localhost
port: 6379
Use Redis as Cache Manager:
@Configuration
public class RedisConfig {
@Bean
public RedisCacheManager cacheManager(RedisConnectionFactory connectionFactory) {
return RedisCacheManager.builder(connectionFactory).build();
}
}
Result: The cache is shared across multiple instances, perfect for cloud deployments!
Common Cache Mistakes to Avoid
Forgetting to update the cache when data changes
Use @CachePut to update cache when saving new data
@CachePut(value = "users", key = "#user.id")
public User saveUser(User user) {
return userRepository.save(user);
}
Caching large objects
Cache only frequent, small, and non-sensitive data
Not setting an expiration time
Always define TTL to prevent outdated data issues