Backend Development 11 min read

Why Redis Increment Returns Null When Using @Transactional with Transaction Support in Spring Boot

The production failure where a customer‑service event creation stopped each morning was traced to RedisTemplate’s increment returning null because @Transactional combined with enabled Redis transaction support caused the command to be queued in a MULTI/EXEC block, which is fixed by using separate non‑transactional and transactional StringRedisTemplate beans.

Java Tech Enthusiast
Java Tech Enthusiast
Java Tech Enthusiast
Why Redis Increment Returns Null When Using @Transactional with Transaction Support in Spring Boot

The article describes a production issue where creating a customer‑service event fails every morning until the microservice is restarted. The failure is caused by the Redis increment operation returning null , which leads to a cascade of errors.

Initial investigation shows that the code uses return redisTemplate.opsForValue().increment("count", 1); and that the increment call returns null only in the early‑morning runs. The team first hypothesized a connection‑leak, but other Redis‑using features worked fine, so this was ruled out.

The second hypothesis focused on Redis transactions. Official Redis documentation states that increment returns null when executed inside a pipeline or a transaction. The service implementation is annotated with @Transactional , which may cause the Redis command to be treated as part of a transaction.

Experiments were performed:

When Redis transaction support is disabled, the increment call returns the expected numeric value, regardless of the @Transactional annotation.

When Redis transaction support is enabled ( setEnableTransactionSupport(true) ) and the method is marked with @Transactional , the increment call consistently returns null , reproducing the production symptom.

Root cause analysis revealed that enabling Redis transaction support makes RedisTemplate bind a connection. Inside a Spring @Transactional method, the bound connection treats the increment as part of a Redis MULTI/EXEC block, queuing the command and returning null until the transaction is committed.

Two remediation strategies are proposed:

Disable transaction support after each Redis transaction. This approach works but still fails if a Redis command is issued inside a @Transactional method while the transaction is active.

Use two separate StringRedisTemplate beans: one with transaction support for explicit Redis transaction scenarios, and another without transaction support for ordinary Redis commands. The configuration example: \@Bean\npublic StringRedisTemplate stringRedisTemplate(RedisConnectionFactory factory) {\n StringRedisTemplate template = new StringRedisTemplate(factory);\n template.setEnableTransactionSupport(false);\n return template;\n}\n\@Bean\npublic StringRedisTemplate stringRedisTemplateTransaction(RedisConnectionFactory factory) {\n StringRedisTemplate template = new StringRedisTemplate(factory);\n template.setEnableTransactionSupport(true);\n return template;\n} Service classes can then inject the appropriate bean and avoid the null result.

After applying the second solution, the Redis increment returns the correct count value even inside @Transactional methods, and the original production issue is resolved.

debuggingJavaMicroservicesTransactionRedisSpring BootTransactional
Java Tech Enthusiast
Written by

Java Tech Enthusiast

Sharing computer programming language knowledge, focusing on Java fundamentals, data structures, related tools, Spring Cloud, IntelliJ IDEA... Book giveaways, red‑packet rewards and other perks await!

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.