In high-throughput applications, repeatedly fetching data from the database can become a bottleneck. Caching is one of the most effective ways to reduce latency, improve response time, and offload database load.
In this guide, we explore how to implement Redis Distributed Caching in Spring Boot, giving your applications a performance boost while maintaining consistency and scalability. We’ll cover setup, configuration, and advanced use cases using Redis as a cache provider.

π Why Redis for Distributed Caching?
Redis (Remote Dictionary Server) is an in-memory data store known for its speed, simplicity, and versatility. It’s widely used for:
- Low-latency key-value caching
- Session management
- Pub/Sub messaging
- Distributed locks
When used as a distributed cache, Redis ensures consistency across clustered environments β making it ideal for microservices and horizontally scaled Spring Boot apps.
π§ Spring Boot + Redis: How It Works
Spring Boot provides native support for Redis through Spring Data Redis and the caching abstraction (@Cacheable
, @CachePut
, @CacheEvict
).
π¦ Maven Dependencies
1 2 3 4 5 6 7 8 9 10 11 12 13 |
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-cache</artifactId> </dependency> </dependencies> |
βοΈ Configuration for Redis
application.yml
1 2 3 4 5 6 7 8 9 |
spring: cache: type: redis redis: host: localhost port: 6379 |
π§ Enable Caching in Spring Boot
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
package com.kscodes.springboot.advanced; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cache.annotation.EnableCaching; @SpringBootApplication @EnableCaching public class RedisCacheApplication { public static void main(String[] args) { SpringApplication.run(RedisCacheApplication.class, args); } } |
π‘ Caching with @Cacheable
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
package com.kscodes.springboot.advanced.service; import org.springframework.cache.annotation.Cacheable; import org.springframework.stereotype.Service; @Service public class ProductService { @Cacheable(value = "products", key = "#productId") public String getProductById(String productId) { simulateSlowService(); return "Product-" + productId; } private void simulateSlowService() { try { Thread.sleep(3000); } catch (InterruptedException e) { throw new IllegalStateException(e); } } } |
The first call will take ~3 seconds
Subsequent calls are instant due to Redis caching
π Updating Cache with @CachePut
1 2 3 4 5 6 7 |
@CachePut(value = "products", key = "#productId") public String updateProduct(String productId) { return "Updated-Product-" + productId; } |
β Removing Cached Values with @CacheEvict
1 2 3 4 5 6 7 |
@CacheEvict(value = "products", key = "#productId") public void deleteProduct(String productId) { // logic to delete product } |
π§ͺ Testing the Cache (Optional REST Controller)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
package com.kscodes.springboot.advanced.controller; import com.kscodes.springboot.advanced.service.ProductService; import org.springframework.web.bind.annotation.*; @RestController @RequestMapping("/product") public class ProductController { private final ProductService service; public ProductController(ProductService service) { this.service = service; } @GetMapping("/{id}") public String getProduct(@PathVariable String id) { return service.getProductById(id); } @PutMapping("/{id}") public String updateProduct(@PathVariable String id) { return service.updateProduct(id); } @DeleteMapping("/{id}") public void deleteProduct(@PathVariable String id) { service.deleteProduct(id); } } |
π οΈ Advanced Redis Config (Custom TTL and Serializer)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
package com.kscodes.springboot.advanced.config; import org.springframework.cache.annotation.EnableCaching; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.redis.cache.RedisCacheConfiguration; import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.data.redis.cache.RedisCacheManager; import org.springframework.data.redis.serializer.*; import java.time.Duration; @Configuration @EnableCaching public class RedisConfig { @Bean public RedisCacheManager cacheManager(RedisConnectionFactory connectionFactory) { RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig() .entryTtl(Duration.ofMinutes(10)) .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer( new GenericJackson2JsonRedisSerializer())); return RedisCacheManager.builder(connectionFactory).cacheDefaults(config).build(); } } |
π§Ό Best Practices for Redis Caching
Practice | Benefit |
---|---|
Use TTLs (Time-to-Live) | Prevent stale data |
Cache only expensive operations | Saves memory and avoids unnecessary cache |
Use cache partitioning | Avoid key collisions |
Monitor with Redis CLI or Grafana | Performance visibility |
π Performance Gains Example
Operation | Without Redis | With Redis |
---|---|---|
Fetch product by ID | 3s | 10ms |
Update and re-fetch | 3s | 10ms |
π³ Dockerize Redis (Optional)
1 2 3 4 |
docker run -d -p 6379:6379 --name redis redis |
π Conclusion
Redis Distributed Caching in Spring Boot supercharges your application performance while maintaining scalability and simplicity. With just a few lines of configuration and annotations, you gain massive speed improvements, database load reduction, and better user experience.
Caching is not a luxury β itβs a necessity in modern applications. Redis, with Spring Boot, offers a robust, production-ready caching solution that scales seamlessly.