Spring Boot Redis Cache Example using @Cacheable, @CachePut and @CacheEvict java Redis Spring Boot Spring Boot 3 by devs5003 - June 10, 20260 Spring Boot Redis Cache Example using @Cacheable, @CachePut and @CacheEvict Many times, we observe that our Spring Boot application becomes slow when it repeatedly fetches the same data from the database. In such cases, caching is one of the best techniques to improve application performance. Redis is one of the most popular in-memory data stores used for implementing high-performance caching in Spring Boot applications. By storing frequently accessed data in memory, Redis can dramatically reduce database load and improve application response times. Spring Boot simplifies cache management through its powerful caching abstraction. With annotations such as @Cacheable, @CachePut, and @CacheEvict, developers can add caching capabilities with minimal code changes while maintaining clean and maintainable applications. In this article, we will learn how to implement Redis Cache in a Spring Boot application using Spring Data Redis. We will create a simple REST API, connect it with MySQL, enable Redis caching, and test whether the cache is working properly or not. By the end of this guide, you’ll have a solid understanding of Redis caching in Spring Boot and be able to implement production-ready caching strategies in your Java applications. Quick Solution: To implement Redis Cache in Spring Boot, add Spring Data Redis and Spring Cache dependencies, configure Redis connection properties, enable caching using @EnableCaching, and apply caching annotations such as @Cacheable, @CachePut, and @CacheEvict on service methods. Table of Contents Toggle What Can You Expect From This Article?Technologies UsedWhat Is Redis?What Is Redis Cache?Why Should We Use Redis Cache?How Does Redis Cache Work?Important Spring Cache AnnotationsStep-by-Step Guide: Spring Boot Redis Cache ExampleStep#1: Add Required DependenciesStep#2: Configure Redis And MySQLStep#3: Enable CachingStep#4: Create Entity ClassStep#5: Create RepositoryStep#6: Create Custom ExceptionStep#7: Create Service LayerStep#8: Create REST ControllerHow To Start Redis Server?How To Test Redis Cache?How To Cache List And Map Objects In Redis?Common Issues And SolutionsRedis Cache Is Not WorkingDatabase Query Still Executes Every TimeCache Returns Old DataWhen Should We Use @Caching Annotation?How To Implement Conditional Caching?ConclusionRelated What Can You Expect From This Article? After going through this article, you will be able to answer the following questions: What is Redis? What is Redis Cache? Why should we use Redis Cache in Spring Boot? How does Redis Cache work? How to configure Redis in Spring Boot? How to use @Cacheable, @CachePut, and @CacheEvict in Spring Boot Redis Cache Example? How to test Redis Cache using REST APIs and Redis CLI? What are the common issues while using Redis Cache? Technologies Used In this example, we are using: Java 17+ Spring Boot 3.x Spring Data JPA Spring Data Redis MySQL 8 Redis Server Maven Postman or any REST client What Is Redis? Redis stands for Remote Dictionary Server. It is an open-source, in-memory data store that can be used as a database, cache, message broker, and streaming engine. Redis stores data in key-value format and supports data structures such as strings, hashes, lists, sets, sorted sets, streams, bitmaps, and more. What Is Redis Cache? Redis Cache is a caching mechanism where frequently accessed data is stored in Redis memory. When the same data is requested again, the application can return it from Redis instead of calling the database again. This reduces database calls and improves application response time. Why Should We Use Redis Cache? We should use Redis Cache when: The same data is requested frequently. Database calls are increasing response time. The application needs faster read performance. We want to reduce load on the database. The data does not change every second. However, we should not cache every piece of data. If the data changes very frequently or must always be real-time, caching may create stale data issues if not handled properly. How Does Redis Cache Work? Let’s understand it in a simple way. When the user calls an API for the first time, the application fetches data from the database and stores the result in Redis Cache. When the same API is called again with the same input, Spring Boot checks Redis first. If the data is available in Redis, it returns the cached result and avoids the database call. For update and delete operations, we should also update or remove the related cache entries. Otherwise, users may receive old data from the cache. Important Spring Cache Annotations Spring provides multiple annotations for caching. @EnableCaching enables caching support in the Spring Boot application. @Cacheable stores the method result in cache. If the same method is called again with the same key, the cached result is returned. @CachePut updates the cache while still executing the method. @CacheEvict removes data from the cache. @Caching is used when we want to apply multiple caching annotations on the same method. Step-by-Step Guide: Spring Boot Redis Cache Example In this example, we will create a simple Invoice REST application. We will apply Redis Cache on retrieve, update, and delete operations. Step#1: Add Required Dependencies Add the following dependencies in pom.xml: org.springframework.boot spring-boot-starter-cache org.springframework.boot spring-boot-starter-data-redis Also add Spring Web, Spring Data JPA, MySQL Driver, and Lombok if you are using them in your project. Step#2: Configure Redis And MySQL Add the following properties in application.properties: spring.datasource.url=jdbc:mysql://localhost:3306/rediscachetest spring.datasource.username=root spring.datasource.password=**** spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver spring.jpa.hibernate.ddl-auto=update spring.jpa.show-sql=true spring.cache.type=redis spring.data.redis.host=localhost spring.data.redis.port=6379 spring.cache.redis.time-to-live=10m spring.cache.redis.cache-null-values=false The ‘time-to-live’ property defines how long cache data should remain available in Redis. Step#3: Enable Caching Add @EnableCaching in the main Spring Boot class. @SpringBootApplication @EnableCaching public class RedisCacheApplication { public static void main(String[] args) { SpringApplication.run(RedisCacheApplication.class, args); } } Step#4: Create Entity Class @Entity @Data @NoArgsConstructor @AllArgsConstructor public class Invoice implements Serializable { private static final long serialVersionUID = 1L; @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Integer invId; private String invName; private Double invAmount; } Step#5: Create Repository @Repository public interface InvoiceRepository extends JpaRepository { } Step#6: Create Custom Exception @ResponseStatus(HttpStatus.NOT_FOUND) public class InvoiceNotFoundException extends RuntimeException { public InvoiceNotFoundException(String message) { super(message); } } Step#7: Create Service Layer The service implementation is the most important part of this example because we apply caching annotations here. @Service public class InvoiceServiceImpl implements InvoiceService { private final InvoiceRepository invoiceRepository; public InvoiceServiceImpl(InvoiceRepository invoiceRepository) { this.invoiceRepository = invoiceRepository; } @CacheEvict(value = "invoicesList", allEntries = true) public Invoice saveInvoice(Invoice invoice) { return invoiceRepository.save(invoice); } @Cacheable(value = "invoice", key = "#invId") public Invoice getOneInvoice(Integer invId) { return invoiceRepository.findById(invId) .orElseThrow(() -> new InvoiceNotFoundException("Invoice not found")); } @Cacheable(value = "invoicesList") public List getAllInvoices() { return invoiceRepository.findAll(); } @Caching( put = @CachePut(value = "invoice", key = "#invId"), evict = @CacheEvict(value = "invoicesList", allEntries = true) ) public Invoice updateInvoice(Invoice invoice, Integer invId) { Invoice existingInvoice = invoiceRepository.findById(invId) .orElseThrow(() -> new InvoiceNotFoundException("Invoice not found")); existingInvoice.setInvName(invoice.getInvName()); existingInvoice.setInvAmount(invoice.getInvAmount()); return invoiceRepository.save(existingInvoice); } @Caching(evict = { @CacheEvict(value = "invoice", key = "#invId"), @CacheEvict(value = "invoicesList", allEntries = true) }) public void deleteInvoice(Integer invId) { Invoice invoice = invoiceRepository.findById(invId) .orElseThrow(() -> new InvoiceNotFoundException("Invoice not found")); invoiceRepository.delete(invoice); } } Here, we are also clearing the invoicesList cache during save, update, and delete operations. This is important because if the list is already cached and we modify one invoice, the list cache may otherwise return old data. Step#8: Create REST Controller @RestController @RequestMapping("/api/invoices") public class InvoiceController { private final InvoiceService invoiceService; public InvoiceController(InvoiceService invoiceService) { this.invoiceService = invoiceService; } @PostMapping public Invoice saveInvoice(@RequestBody Invoice invoice) { return invoiceService.saveInvoice(invoice); } @GetMapping("/{id}") public Invoice getOneInvoice(@PathVariable Integer id) { return invoiceService.getOneInvoice(id); } @GetMapping public List getAllInvoices() { return invoiceService.getAllInvoices(); } @PutMapping("/{id}") public Invoice updateInvoice(@RequestBody Invoice invoice, @PathVariable Integer id) { return invoiceService.updateInvoice(invoice, id); } @DeleteMapping("/{id}") public String deleteInvoice(@PathVariable Integer id) { invoiceService.deleteInvoice(id); return "Invoice with id " + id + " deleted successfully"; } } How To Start Redis Server? If you are using Docker, you can start Redis using the following command: docker run --name redis-cache -p 6379:6379 -d redis:latest To check whether Redis is running or not: redis-cli ping If Redis is running, it will return: PONG How To Test Redis Cache? Start Redis Server first. Then start the Spring Boot application. Now call the API for the first time: GET http://localhost:8080/api/invoices/1 For the first call, you should see a SQL query in the application console because data is fetched from the database. Call the same API again. This time, the SQL query should not be printed because data should come from Redis Cache. You can also check Redis keys using: redis-cli keys "*" For local testing, KEYS * is fine. In production, prefer SCAN because KEYS can be expensive when Redis has many keys. How To Cache List And Map Objects In Redis? Yes, we can cache collection objects such as List and Map in Redis. In the above example, getAllInvoices() caches a List. @Cacheable(value = "invoicesList") public List getAllInvoices() { return invoiceRepository.findAll(); } If you are caching complex objects, make sure the object is serializable or configure JSON serialization using a custom RedisCacheManager. Common Issues And Solutions Redis Cache Is Not Working Check the following points: @EnableCaching is added in the main class. Redis Server is running. spring.cache.type=redis is configured. The cached method is called from another Spring bean. The cache key is correct. The method returns a value. Database Query Still Executes Every Time This can happen if the method arguments are different, the key is not matching, or the method is being called internally from the same class. Spring caching works through proxies, so self-invocation can bypass caching. Cache Returns Old Data Use @CachePut for update operations and @CacheEvict for delete operations. Also evict list caches when saving, updating, or deleting records. When Should We Use @Caching Annotation? We should use @Caching when we need to apply multiple caching operations on the same method. For example, during update, we may want to update one cache entry and remove the list cache at the same time. @Caching( put = @CachePut(value = "invoice", key = "#invId"), evict = @CacheEvict(value = "invoicesList", allEntries = true) ) How To Implement Conditional Caching? Spring also supports conditional caching using condition and unless. @Cacheable(value = "invoice", key = "#invId", condition = "#invId > 10") public Invoice getOneInvoice(Integer invId) { return invoiceRepository.findById(invId).orElseThrow(); } Here, caching will be applied only when invId is greater than 10. Conclusion In this article, we learned how to implement Redis Cache in a Spring Boot application step by step. We created a simple Invoice REST API, configured Redis, enabled caching, and used important annotations such as @Cacheable, @CachePut, @CacheEvict, and @Caching. Redis Cache is very useful when we want to reduce database calls and improve application performance. However, we should always update or evict cache entries properly during save, update, and delete operations to avoid stale data. References: Spring Boot Caching Spring Cache Annotations Spring Data Redis Cache You may also go through ‘How to download Redis Server?‘ and Spring Boot Redis CRUD Example. Related