Redis Clients for Java: Jedis, Lettuce, Redisson

A Redis Java client is the library that sits between your Java code and a Redis or Valkey server. It opens the TCP connections, turns method calls into commands in the Redis serialization protocol (RESP), and turns the replies back into Java objects. The server has no Java API of its own, so every Java application that uses Redis goes through a client library.

Three clients are in wide use today. Redis maintains two of them, Jedis and Lettuce. Redisson is independent and supports both Redis and Valkey. All three cover the core command set. They differ in how they manage connections, threads, asynchronous calls and caching, and in whether they support Valkey.

Choosing a Redis Java Client by Use Case

Most teams can narrow the choice from the shape of the application before comparing features:

If you are buildingThe usual choiceRead next

A Spring Boot application that uses Spring's caching or data-access abstractions

Lettuce, through Spring Data Redis. It is Spring Boot's default driver.

Redis with Spring Boot and the Lettuce guide

Plain blocking code with a Java 8 baseline and few dependencies

Jedis, using its RedisClient class

The Jedis guide

A Valkey deployment, or a planned move from Redis to Valkey

Redisson, the one client here that states support for both servers

What is a Valkey Java client? and migrating from Redis to Valkey in Java

Locks, shared collections, near caches or (with Redisson PRO) reliable queues that span several JVMs

Redisson

How to use Redis or Valkey in Java

A decision between Jedis and Lettuce only

Depends on threading and API style

Jedis vs Lettuce

Teams often start on one client and add another later, for example Redisson for locks or caching alongside an existing Jedis, Lettuce or Spring Data Redis setup. The side-by-side comparisons cover Redisson vs Jedis, Redisson vs Lettuce and Redisson vs Spring Data Redis. The migration guides cover moving from Jedis, Lettuce, Spring Data Redis and Valkey GLIDE.

Redis Java Clients Compared: Jedis, Lettuce and Redisson

Versions are the latest releases on Maven Central as of October 23, 2026. Pre-releases are left out.

JedisLettuceRedisson

Latest release

8.0.2

7.9.0.RELEASE

4.8.0

Maintained by

Redis

Redis

Redisson

API styles

Synchronous

Synchronous, asynchronous, reactive

Synchronous, asynchronous, Reactive Streams, RxJava

Connection model

Connection pool, managed inside RedisClient

One shared, multiplexed connection (one per node in cluster mode)

Asynchronous connection pool per node, 64 by default; multiplexed when the pool size is set below 10

Thread-safe client object

RedisClient: yes. The Jedis class: no

Yes

Yes

Client-side caching

Since 5.2.0; needs RESP3 and Redis 7.4 or later, and by default refuses to start against Valkey

ClientSideCaching, deprecated since 7.8

RClientSideCaching (RESP3), plus near-cache maps that invalidate per entry

Distributed locks and collections

No

No

Yes (locks, collections, queues, services)

Officially supported servers

Redis 7.2 and later; Valkey not stated

Redis; Valkey not stated

Redis 3.0 and later; Valkey 7.2.5 and later

The sections below explain the rows where the clients differ most.

How a Java Client Talks to Redis

Redis and Valkey speak RESP over TCP. When your code saves a user profile or reads a cached query, the client serializes the call into a RESP command, writes it to a socket, and parses the reply into a Java object such as a String, a Long or a List. Without a client you would open the sockets, build the byte arrays and parse the replies yourself.

RESP comes in two versions. RESP2 is what a connection uses unless the client asks for something else. RESP3, available since Redis 6, adds richer reply types such as maps, sets, booleans and doubles, and it adds push messages, which the Java clients' client-side caching implementations require. A client switches to RESP3 by sending HELLO 3 when it connects. Lettuce has done this by default since version 6.0. Jedis has done it by default since 8.0 for RedisClient and its siblings, while the legacy Jedis class stays on RESP2. Redisson stays on RESP2 unless you set its protocol option to RESP3.

Changing protocol can change the shape of a reply. Under RESP3, HGETALL returns a map instead of a flat array and ZSCORE returns a double instead of a string. A client's typed methods usually hide this, but code that sends raw commands or parses EVAL results itself can break. Test those paths when you upgrade a client whose default has changed.

Connection Pooling vs. Multiplexing

Every client keeps TCP connections open to the server. How it shares them between threads is the biggest design difference between clients:

  • One connection per thread: simple, but an anti-pattern under load. It wastes memory on both sides and runs into the server's connection limit.

  • Connection pooling: the client keeps a pool of open connections. A thread borrows one for a command and returns it afterwards, and no other thread can use that connection in the meantime. Jedis works this way. Its RedisClient manages the pool for you, and the pool size caps how many threads can talk to Redis at once.

  • Multiplexing: many threads share one connection. The client writes their commands onto the socket back to back and matches each reply to its caller as it arrives. This works because the server executes commands one at a time and answers them in order. Lettuce shares one connection this way.

A multiplexed connection handles very high concurrency with few sockets, but some commands hold it up. A blocking command such as BLPOP stops everything queued behind it until it returns. A MULTI/EXEC transaction, especially one that uses WATCH, needs a connection that no other thread writes to, and a very large value delays every reply behind it. Lettuce users open a dedicated connection for these cases. How to use Redis or Valkey in Java covers this limitation and how many connections Redisson opens.

Redisson, built on Netty like Lettuce, uses an asynchronous pool: up to 64 connections per node by default. A command takes a connection for its round trip without blocking the calling thread, so many threads share a small number of sockets. Blocking operations, such as waiting on an RBlockingQueue, hold a connection for as long as they wait without holding up other callers. If you set the pool size below 10, Redisson writes several commands onto each connection before their replies arrive, which is multiplexing in the Lettuce sense. Pub/sub subscriptions have a pool of their own.

Thread Safety

A client object is thread-safe if many threads can call it at the same time without mixing up each other's commands and replies.

The original Jedis class wraps a single socket and is not thread-safe, which is why Jedis code traditionally borrowed connections from a JedisPool. Jedis 4.0 added JedisPooled, a thread-safe class that pooled connections internally. Jedis 7.2 replaced it with RedisClient, which works the same way and is the class Jedis now recommends for new code. The same release deprecated JedisPool, JedisPooled, JedisCluster, JedisSentinelPool and JedisSentineled, and Jedis 8.0 removed JedisPooled and JedisSentineled altogether. Much of the Jedis code published online still uses the old classes.

A Lettuce connection and a RedissonClient are both thread-safe. With any of the three, the usual pattern is to create one client when the application starts, share it everywhere, and close it on shutdown.

Synchronous, Asynchronous and Reactive APIs

Redis Java clients offer up to three programming models:

  • Synchronous, also called blocking. The calling thread sends a command and waits for the reply. Jedis offers only this model.

  • Asynchronous. The call returns a future at once, and the thread can do other work until the reply arrives. Lettuce returns RedisFuture, and Redisson returns RFuture, which implements CompletionStage.

  • Reactive. Results arrive as a stream that the application subscribes to, with back-pressure. Lettuce and Redisson both support Project Reactor, and Redisson also offers an RxJava 3 API.

An asynchronous API is not automatically faster. It lets fewer threads keep more commands in flight, which matters in event-driven applications. In a classic thread-per-request service, a synchronous client with a correctly sized pool is often simpler and fast enough.

Client-Side Caching

Client-side caching keeps recently read values in the application's own memory, so repeated reads skip the network round trip. The hard part is invalidation: knowing when a cached value has changed on the server. Since Redis 6 the server can track which keys a client has read and send it an invalidation message when one of them changes. Under RESP3 those messages arrive on the same connection; under RESP2 the server redirects them to a second one.

  • Jedis has supported client-side caching since 5.2.0. It needs RESP3 and Redis 7.4 or later. It checks the server it connects to and, unless you switch on its compatibility mode, refuses to enable caching against Valkey.

  • Lettuce provides ClientSideCaching and CacheFrontend in its io.lettuce.core.support.caching package. Since 7.8 both are deprecated as legacy and incomplete, and Lettuce says a redesigned API is planned.

  • Redisson offers tracking-based caching for buckets, maps, sets, lists, queues and streams through getClientSideCaching(), which requires RESP3. That mode invalidates a whole object when any entry changes, so for large maps Redisson's near cache, RLocalCachedMap, is the better fit because it invalidates entry by entry. Redisson also plugs into Spring Cache, the Hibernate second-level cache and JCache; the local-cached variants of those integrations are part of Redisson PRO.

For how server-side tracking and invalidation work, see near cache. For Redisson's caching options, see Redis client-side caching, and for caching JSON documents from Java, see JSON client-side caching for Valkey and Redis.

Do Redis Java Clients Support Valkey?

Valkey forked from Redis 7.2.4 in 2024 and kept the protocol and the shared command set, so a client written for Redis can usually connect to Valkey without code changes. Whether the client's maintainers support that combination is a separate question, and the answer differs by client.

Jedis and Lettuce are developed by Redis, and neither states Valkey support. The Jedis documentation lists the Redis versions it supports, from 7.2 to the current 8.x releases, and the source code of the current Jedis and Lettuce releases does not mention Valkey at all. Valkey's own client list, which includes only clients the Valkey project regularly tests and recommends, doesn't list them either. One feature already shows the gap: Jedis client-side caching checks which server it is connected to and, by default, refuses to start against Valkey. The two servers have also diverged since the fork. Redis 8 folded JSON, search and probabilistic data types into the core server, while Valkey ships its own modules.

Redisson states support for both servers: Redis from 3.0 and Valkey from 7.2.5, up to the latest version of each. It accepts valkey:// addresses, and it is one of the three Java clients on Valkey's list.

Valkey's own Java clients, Valkey GLIDE and valkey-java, are covered in What is a Valkey Java client? and compared head to head in Valkey GLIDE vs valkey-java. GLIDE's documentation lists Redis support only for open-source versions up to 7.2, so it is not an option for current Redis releases. Valkey GLIDE vs Redisson compares GLIDE with Redisson on Valkey, and the Valkey Java example shows the same program in all three. For the server-side differences, see Valkey vs Redis, and for moving an application across, see migrating from Redis to Valkey in Java.

Frameworks Built on a Client

Many applications never choose a client directly, because their framework chooses one for them. Spring Data Redis is an abstraction over Lettuce or Jedis rather than a client of its own, and Spring Boot configures Lettuce unless you set spring.data.redis.client-type=jedis or exclude Lettuce. Micronaut's Redis module is built on Lettuce. Quarkus ships its own Redis extension. Redisson integrates with all three: it provides a connection factory for Spring Data Redis (compared in Redisson vs Spring Data Redis), and it has integrations for Quarkus and Micronaut.

Configuring a Client for Production

Whichever client you pick, its defaults decide how the application behaves when the network or the server misbehaves. Those defaults include command timeouts, retry behavior, reconnection, pool or connection sizing, and how the client discovers topology changes in a Redis Cluster or behind Sentinel. Valkey and Redis best practices for Java applications walks through the settings that matter. Two production topics are worth reading about before go-live: connecting over TLS and client metrics. If you use Jedis, note that Jedis 8 verifies TLS hostnames by default, which the Jedis guide covers.

Using Redisson as a Redis Java Client

Jedis and Lettuce map Java methods onto Redis commands: you call hset and the client sends HSET. Building distributed behavior on top of those commands is left to you, including object serialization, lock renewal and the retry semantics of multi-step operations. Redisson maps Redis data structures onto familiar Java interfaces instead, and implements some of its objects with Lua scripts so that multi-step operations run atomically on the server. It provides:

  • Distributed collections, such as maps, sets, lists and queues, that implement the java.util interfaces.

  • Distributed concurrency primitives, including locks, semaphores and count-down latches that work across JVMs.

  • Messaging, from pub/sub topics and streams to, in Redisson PRO, Reliable Queue with acknowledgments and delivery limits, Reliable PubSub with acknowledgments and replay, and an implementation of the JMS API.

  • Caching and services, including the Spring Cache, Hibernate and JCache integrations, web session clustering and remote service invocation.

This example connects to a server, uses a distributed map and takes a distributed lock:

// Connect to a single Redis or Valkey server
Config config = new Config();
config.useSingleServer().setAddress("redis://127.0.0.1:6379");
RedissonClient redisson = Redisson.create(config);

// Use Redis through the standard java.util.Map interface
RMap<String, String> users = redisson.getMap("users");
users.put("user:1", "Ada Lovelace");
String name = users.get("user:1");

// A distributed lock, which command-level clients leave to you
RLock lock = redisson.getLock("order:42:lock");
lock.lock();
try {
    // critical section: only one JVM runs this at a time
} finally {
    lock.unlock();
}

redisson.shutdown();

For a full walkthrough, including Maven setup and connection sizing, see how to use Redis or Valkey in Java.

Redis Java Clients: Frequently Asked Questions

Is Jedis Thread-Safe?

The Jedis class is not. It wraps one socket, so two threads using it at once interleave their commands and read each other's replies. RedisClient, added in Jedis 7.2, is thread-safe because it manages a connection pool internally, and it is the class Jedis now recommends for new code. JedisPooled, the earlier thread-safe option from Jedis 4.0, was removed in Jedis 8.0.

Which Redis Client Does Spring Boot Use?

Lettuce. The spring-boot-starter-data-redis starter brings in Lettuce, and Spring Boot configures a LettuceConnectionFactory by default. To use Jedis instead, add the Jedis dependency and set spring.data.redis.client-type=jedis, or exclude Lettuce. Redisson provides its own connection factory for Spring Data Redis.

Does Jedis Support Asynchronous Calls?

No. Jedis is synchronous: each call blocks its thread until the reply arrives. Lettuce and Redisson both offer asynchronous APIs that return futures, as well as reactive APIs.

Do Jedis and Lettuce Support Valkey?

Neither states it. Both are developed by Redis, neither project lists Valkey as supported, and Valkey's list of tested and recommended clients doesn't include them. They usually connect, because Valkey kept the Redis protocol, but Jedis client-side caching refuses to start against Valkey by default. Redisson states support for both Redis and Valkey.

Do Redis Java Clients Support Client-Side Caching?

All three have some form of it. Jedis, from version 5.2.0, uses the server's key tracking and by default works only against Redis 7.4 or later. Lettuce's implementation uses tracking too but has been deprecated since 7.8. Redisson offers tracking-based caching for its objects, plus local-cached maps that invalidate entry by entry.

Similar terms