Migrating from Redis to Valkey in Java: A Complete Guide

Last updated
August 28, 2026

Valkey was forked from Redis OSS 7.2.4 and remains wire- and command-compatible with it. For a Java application, that means migrating is an infrastructure change rather than a code change — provided your client supports both engines. In the common case you are editing a connection string, not rewriting a data layer.

The work that remains is real, though, and it is not where most teams expect. It is not the protocol, the commands or the data structures. It is module dependencies, serialization codecs and cutover mechanics. This guide covers all three, along with the migration paths for each deployment topology.

Why Java Teams Are Moving to Valkey

Almost always, the trigger is licensing rather than technology.

How the licence changed, twice

Every Redis release up to and including 7.2.4 shipped under the permissive BSD 3-Clause licence. In March 2024, Redis Ltd. announced that from version 7.4 the software would ship under a dual model — the Redis Source Available License v2 (RSALv2) and the Server Side Public License v1 (SSPLv1) — neither of which is OSI-approved. Within days the Linux Foundation forked Redis OSS 7.2.4 as Valkey, retaining the BSD licence, with backing from AWS, Google Cloud, Oracle, Ericsson and Snap.

In May 2025 Redis 8.0 added AGPLv3 as a third option, so Redis is once again open source by the OSI definition. That is worth stating plainly, because a lot of migration advice written in 2024 assumes it is not.

Why AGPLv3 is still a blocker

AGPLv3 is strong copyleft: modify the source, run it as a network service, and you may be obliged to publish your modifications. In practice, ordinary use of an unmodified data store rarely triggers those obligations. That is not the point. Many enterprises maintain blanket policies prohibiting AGPL-licensed dependencies anywhere in the stack, because legal teams are wary of the copyleft reach rather than the specific facts of any one deployment.

The result is that the decision is frequently made by procurement or legal, and lands on an engineering team as a requirement rather than a question. If that is your situation, the rest of this guide is the practical part.

If you have not settled on Valkey yet and are still weighing other engines, start with Redis alternatives — it compares Valkey, Dragonfly, KeyDB and Garnet on the compatibility rows that decide a migration, and explains why a move from AGPL to a source-available licence often fails the same review.

What you gain on arrival

Valkey has not stood still since the fork. Valkey 8.0 introduced asynchronous I/O threading and a per-slot dictionary that cuts roughly 16 bytes of overhead per key-value pair. Valkey 9.0 added hash field expiration, multi-database support in cluster mode, SIMD acceleration across several hot paths, and — per AWS — up to 40% higher throughput on pipelined workloads. Valkey 9.1.1 is the current stable release as of July 2026, with the 9.1, 9.0, 8.1, 8.0 and 7.2 lines all actively maintained.

Several newer commands are directly useful during a migration, and are covered in the paths below. A separate set of Valkey-only settings only becomes relevant once the cutover is done — those are gathered after the module section.

What Changes for Your Java Application, and What Doesn't

The RESP protocol is unchanged. The core command surface is unchanged. Core data types behave identically. What determines your migration path is how far past the 7.2.4 fork point you have drifted.

Your current RedisRecommended targetJava code changesWatch out for
Redis 7.2.4 or earlierValkey 9.1NoneNothing. Valkey forked from exactly here, so this is effectively an upgrade
Redis 7.4.xValkey 9.1None expectedHash field TTL arrived in Redis 7.4 and Valkey 9.0. Fine on 9.1, breaks if you target Valkey 8.x
Redis 8.0–8.8Valkey 9.1None for coreRedis 8 folded the Stack modules into core. You may have picked up dependencies without logging them. Redis 8.8's Array type and INCREX have no Valkey equivalent
Redis Stack, any versionValkey 9.1 plus modulesDependsThis is where the real work is. See the module section below
Redis Enterprise or Redis CloudManaged or self-managed ValkeyPossibleRedis Enterprise's Active-Active CRDB, which is multi-master with conflict-free replicated types, has no open-source Valkey equivalent. Some managed Valkey services do offer native cross-region replication, so check your target before assuming the capability is gone
ElastiCache for Redis OSSElastiCache for Valkey 9.0NoneIn-place engine change. AWS lists Valkey as the recommended ElastiCache engine and prices it 20% below Redis OSS on node-based clusters
MemoryDB for RedisMemoryDB for ValkeyNoneMemoryDB is durable by design; ElastiCache added opt-in durability only from Valkey 9.0. Confirm which model your target uses rather than reusing an existing runbook
Memorystore for RedisMemorystore for Valkey 9.0NoneA separate product, so a new instance rather than an in-place upgrade — but Google provides migration support and lets you carry committed use discounts across
Azure Cache for RedisSelf-managed Valkey, typically on AKSNoneNo first-party Azure Valkey service. Note also that Azure Cache for Redis is being retired — Enterprise tiers on 31 March 2027, Basic/Standard/Premium on 30 September 2028 — so you face a migration regardless

Java client support

The Valkey project lists three recommended Java clients: Redisson, Valkey GLIDE and valkey-java. Other clients that support Redis OSS 7.2 will generally connect, since the wire protocol is shared, but they are not part of the tested set.

Redisson supports Valkey deployments from 7.2.5 through current releases and accepts the valkey://, valkeys:// (TLS) and valkey+uds:// (Unix domain socket) URL schemes alongside the traditional redis:// forms. Because the same client, the same API and the same objects work against both engines, the engine choice never reaches your application code — and a rollback is a configuration revert rather than a redeployment.

Pre-Migration Checklist

Complete this before choosing a path. Most migrations that go badly go badly because something on this list was discovered during the cutover instead of before it.

  • Topology — standalone, Sentinel, Cluster or managed
  • Redis version — determines your row in the table above
  • Modules — run MODULE LIST against every primary node. Do this first; it is the most common source of surprises
  • Lua scripts — inventory every EVAL and FUNCTION you depend on, including those your client issues on your behalf
  • Persistence — RDB, AOF or both, and the current file versions
  • Auth and ACLs — users, rules, and whether you use TLS
  • Client library and version — pin it, and read the next section on codecs before you upgrade it
  • Serialization codec — the single most dangerous item on this list
  • Baseline metrics — key count, memory footprint, p99 latency. You cannot verify a migration without a before

Choose Your Migration Path

PathDowntimeRollbackBest for
A — Standalone, snapshot copyBrief pauseSimpleSmall datasets, tolerant workloads
A — Standalone, live replicationNoneSimpleAnything write-heavy
B — SentinelFailover onlyModerateExisting HA deployments
C — ClusterNoneModerateSharded production estates
D — Managed serviceProvider-dependentVariesElastiCache, MemoryDB, Memorystore

Path A: standalone Redis to Valkey

Two options. The simplest is a snapshot copy: disconnect active connections, take a fresh RDB with BGSAVE, copy the file to the Valkey host and start Valkey against it. Valkey loads the snapshot on startup. The trade-off is downtime while Valkey loads, plus a risk of losing writes on a busy instance if connections are not fully drained.

The lower-risk option is live replication: configure the Valkey instance as a replica of the Redis primary with REPLICAOF, let it sync, then promote it and repoint clients. Valkey also provides CLIENT IMPORT-SOURCE, which marks a connection as an import source while the server is in import mode. If you are driving the copy with a migration tool rather than with replication, check whether it supports this.

Path B: Redis Sentinel to Valkey Sentinel

Add Valkey replicas to the existing Sentinel-monitored set, allow them to sync, then trigger a failover so a Valkey node becomes primary. Retire the Redis nodes once the topology is stable. The one detail teams routinely miss: masterName is configured on the Sentinel side, and a mismatch between it and your client configuration is a silent failure at cutover, not a startup error.

Path C: Redis Cluster to Valkey Cluster

Add Valkey nodes to the existing cluster as replicas, wait for replication to complete, then promote one Valkey replica per Redis primary. No downtime is required. Note that this path runs on replication and failover, not slot movement — the mixed Redis and Valkey cluster you have mid-migration cannot use Valkey-specific cluster commands. Once you are fully on Valkey, resharding gets easier: CLUSTER MIGRATESLOTS performs atomic slot migration, with CLUSTER GETSLOTMIGRATIONS for observable progress and CLUSTER CANCELSLOTMIGRATIONS to abort. That is a capability you gain on arrival rather than a tool for the crossing.

This path has enough operational detail to deserve its own treatment. We cover it step by step in Migrating Your Java App from Redis Cluster to Valkey Cluster, and the related mechanics in How to Upgrade a Valkey Cluster With Zero Downtime.

Path D: managed services

On AWS, moving ElastiCache or MemoryDB to Valkey is an engine change handled by the provider, and AWS lists Valkey as its recommended ElastiCache engine. There is usually a cost argument alongside the licensing one: AWS prices Valkey 20% below other supported engines on node-based clusters and 33% below on Serverless, which on a mid-sized production cluster is a line item large enough to get the migration approved on its own. Memorystore for Valkey 9.0 is generally available. It is a separate product from Memorystore for Redis, so this is a new instance rather than an in-place upgrade, but Google provides migration support and lets you reuse existing committed use discounts. One detail that matters if you are coming from standalone Redis: Memorystore for Valkey can run with cluster mode disabled, which lets you move engines without also being forced into a cluster topology. You give up sharding and are capped at two replicas, but the application impact is far smaller. Azure has no first-party Valkey service, so the realistic route is self-managed Valkey on AKS.

Migrating the Java Layer with Redisson

Step 1: repoint the client

This is the entire application-side change for most deployments:

singleServerConfig:
  address: "valkey://valkey-host:6379"

The same applies across topologies. Cluster mode:

Config config = new Config();
config.useClusterServers()
      .setScanInterval(1000)
      .addNodeAddress(
          "valkey://valkey-node-1:6379",
          "valkey://valkey-node-2:6379",
          "valkey://valkey-node-3:6379");

RedissonClient redisson = Redisson.create(config);

You only need to seed a subset of nodes — Redisson discovers the rest and refreshes topology on scanInterval, which matters during a migration precisely because nodes are being added and promoted while the client is live. Sentinel mode uses useSentinelServers() with setMasterName(); managed services use useReplicatedServers(), almost always with the TLS valkeys:// scheme, since managed Valkey generally enforces in-transit encryption.

Two version notes. Redisson added a database setting for Valkey Cluster mode in 4.0.0, matching Valkey 9.0's multi-database support — see the settings section for what that needs server side. More importantly, use Redisson 4.3.1 or later if you are migrating on AWS — that release fixed a bug where the master connection could freeze during an ElastiCache Valkey upgrade, which is exactly the operation you are about to perform.

Step 2: swap the client, if you are not already on Redisson

If you are coming from Spring Data Redis, Redisson supplies a connection factory that plugs into Spring's RedisConnectionFactory abstraction, so existing RedisTemplate wiring is preserved rather than rewritten. Check the current class and module against the version you are pinning — Redisson reorganised its Spring modules during the 4.x line. We have dedicated guides for Jedis, Lettuce, Spring Data Redis and Valkey GLIDE.

On Spring Boot property keys, one clarification that causes repeated confusion: Redisson's own prefix is spring.redis.redisson.* and has not changed. What changed is Spring Boot's own connection properties, which moved from spring.redis.* to spring.data.redis.* in Spring Boot 3.0. Redisson resolves those reflectively so the starter tolerates multiple Boot versions.

Step 3: verify your serialization codec — read this before upgrading Redisson

Values are opaque bytes to the server. It is your codec, not the engine, that determines whether data written before the migration is readable after it. Because Valkey stores the same bytes Redis did, an engine change alone is safe.

The danger is bundling a client upgrade into the same change. Redisson 4.1.0 removed FstCodec, FuryCodec, MarshallingCodec and SnappyCodec. If you are on an older Redisson using one of those and you upgrade as part of this project, the codec class is gone and your existing cached data becomes unreadable. It will present as a migration failure when it is actually a client upgrade failure, and you will spend a day looking in the wrong place.

Migrate the engine and upgrade the client as two separate changes, in that order. Confirm codec parity first, cut over to Valkey second, upgrade Redisson third. Our guide to choosing a Redisson codec covers the current options.

Other breaking changes worth checking if you are jumping several versions: Redisson 4.0.0 dropped the deprecated JSON config format and Spring XML configuration, renamed the RScript.ReturnType values, and moved NameMapper, NatMapper, the Geo* and the Stream* classes into new packages.

Step 4: run a validation window

Before cutting over, run both engines in parallel. Shadow reads are the cheapest useful version: serve production reads from Redis while issuing the same reads against Valkey and comparing results asynchronously. If your workload tolerates it, dual-write for a period as well. The goal is to catch a module or Lua incompatibility under real traffic rather than under synthetic tests.

Step 5: cut over, and keep a way back

Do not decommission the Redis instance at cutover. Leave it running read-only through a validation window. Because Redisson connects to both engines through the same API, rolling back means reverting a connection string and restarting — no code change, no redeployment, no dependency swap.

Step 6: verify

Compare key counts with DBSIZE and INFO KEYSPACE against your pre-migration baseline. In cluster mode, Valkey's CLUSTERSCAN iterates keys across the whole cluster, which makes a full reconciliation pass straightforward. Then compare p99 latency and error rates against baseline using Redisson client metrics and tracing. A migration is not finished when it connects; it is finished when the numbers match.

Replacing Redis Stack Modules

This is where migrations actually fail, so audit it early. Redis 8 folded the Stack modules into core. Valkey provides equivalents as separate BSD-licensed modules — valkey-json, valkey-bloom, valkey-search and valkey-ldap — which ship together in the valkey-bundle container. If you are moving to a managed service, check what it already includes before planning module deployment: Memorystore for Valkey, for instance, supports Bloom filters and JSON. Coverage is uneven either way.

Redis capabilityValkey equivalentRedisson objectModule needed?
RedisJSONvalkey-json — near-completeRJsonBucket, RJsonStoreYes
RediSearchvalkey-search — partial, see belowRSearchYes, with gaps
Bloom filtervalkey-bloomRBloomFilter or RBloomFilterNativeOptional
RedisTimeSeriesNoneRTimeSeriesNo
Cuckoo filterNoneRCuckooFilterYes — no Valkey path
Top-KNoneRTopKYes — no Valkey path
T-DigestNoneRTDigestYes — no Valkey path
Count-Min SketchNoneNoneRebuild client-side
RedisGraphNoneNoneDeprecated by Redis too — migrate off regardless

Time series: the good news

Valkey has no TS.* commands at all, which makes RedisTimeSeries the hardest blocker in most migrations. Redisson's RTimeSeries resolves it: the implementation uses no module commands, only EVAL against core data structures, so it works against any Valkey or Redis deployment. Valkey ships the complete scripting surface — EVAL, EVALSHA, the read-only variants, FCALL and the full FUNCTION and SCRIPT families — so this path is clean. The same is true of Redisson's standard RBloomFilter, which needs no module either.

Probabilistic structures: the bad news

Redisson's RCuckooFilter, RTopK and RTDigest wrap the server's CF.*, TOPK.* and TDIGEST.* commands rather than reimplementing them. Valkey provides none of those commands, so these objects cannot work against Valkey — and neither can any other client's equivalent, because the commands are simply not there. If your application uses Cuckoo filters, Top-K or T-Digest, there is currently no Valkey path for them. Find this during evaluation, not during a cutover.

Search: a genuine subset

valkey-search exposes six commands — FT.CREATE, FT.SEARCH, FT.AGGREGATE, FT.INFO, FT.DROPINDEX and FT._LIST. Absent are FT.PROFILE, FT.CURSOR, FT.ALTER, FT.EXPLAIN, index aliasing, FT.TAGVALS, autocomplete, synonyms, spellcheck and dictionaries. FT.SEARCH itself takes a reduced option set, and GEOSHAPE index fields are unsupported. Core geospatial polygon search is a separate matter — Valkey 9.0 added a BYPOLYGON option to GEOSEARCH — but that does not help an indexed GEOSHAPE query.

Concretely, three Redisson calls compile and then fail against valkey-search: profileSearch() and profileAggregate() require FT.PROFILE; readCursor() requires FT.CURSOR; and createIndex() with a GEOSHAPE field requires a type Valkey does not implement. Index creation, search, aggregation, info() and dropIndex() all work. If your search layer stays inside that core set, you are fine.

Valkey-Only Settings Worth Turning On After Cutover

Everything above is about arriving on Valkey without changing code, and that holds. But once you are there, two Redisson settings become available that have no counterpart on Redis at all — and one Valkey capability that Redisson does not yet expose. None of the three is required for the migration. All three belong in the post-migration ticket, because two are one line each and the third is a gap worth sizing deliberately rather than discovering on a cloud bill.

Replica redirect: the one that helps Sentinel, not Cluster

This is the counter-intuitive one. Valkey 8.0 added support for a replica to redirect read and write operations to the primary in standalone mode rather than returning an error. A client opts in by declaring the capability at connection time with CLIENT CAPA REDIRECT; the server then answers a misdirected command with -REDIRECT <host>:<port>, and the client re-issues it against the primary. Redis has no CLIENT CAPA command and no equivalent mechanism.

The name misleads people into filing this under cluster features. It is the opposite. Cluster mode already solves this with MOVED and ASK; replica redirect is for the topologies that do not have those — standalone, Sentinel and replicated. Those are precisely the deployments where a failover can leave a client briefly holding a connection to a node that is no longer the primary, and where the alternative to a redirect is an error surfaced into your application.

Redisson has shipped it since 3.47.0 and sends the declaration during the connection handshake in every mode, so the setting lives on Config itself rather than on a topology block:

Config config = new Config();
config.setValkeyCapabilities(Set.of(ValkeyCapability.REDIRECT));
config.useSentinelServers()
      .setMasterName("mymaster")
      .addSentinelAddress(
          "valkey://valkey-sentinel-1:26379",
          "valkey://valkey-sentinel-2:26379",
          "valkey://valkey-sentinel-3:26379");

RedissonClient redisson = Redisson.create(config);

The default is empty, so this is opt-in: a configuration you simply repointed at Valkey is not using it. Declaring a capability the server does not implement is harmless, which makes it safe to set across a mixed estate during a phased cutover.

Numbered databases in cluster mode

Step 1 mentioned this in passing. It is worth stating what it actually requires, because the Java half is the easy half. Redis rejects the command outright — SELECT is not allowed in cluster mode — and logs a warning that it is forcing the database count to 1 whenever cluster mode is enabled. Valkey 9.0 removed that restriction.

Two things have to line up. Server side, cluster-databases defaults to 1 and is immutable, so raising it is a config change and a restart, not a runtime toggle. Client side, Redisson added database to the cluster configuration in 4.0.0:

Config config = new Config();
config.useClusterServers()
      .setDatabase(3)
      .addNodeAddress(
          "valkey://valkey-node-1:6379",
          "valkey://valkey-node-2:6379",
          "valkey://valkey-node-3:6379");

RedissonClient redisson = Redisson.create(config);

One note for your own runbook: this setting is currently missing from the Cluster section of the Redisson configuration reference, although it is documented for every other topology. It exists and it works from 4.0.0 onward.

The gap: availability-zone affinity

Be clear-eyed about this one, because it is the Valkey feature most likely to show up on a cloud bill. Valkey lets you tag each node with availability-zone and publishes the value through INFO, HELLO and — from 9.1 — CLUSTER SHARDS and CLUSTER SLOTS. The server does no routing with it. It is metadata exposed for clients to act on, and acting on it is entirely a client-side read strategy.

Among Java clients, Valkey GLIDE is currently the only one that implements a strategy on top of it. Redisson's ReadMode offers SLAVE, MASTER and MASTER_SLAVE and carries no zone awareness; neither Lettuce nor Jedis exposes one either. If cross-zone read traffic is a cost line you are actively trying to cut, weigh that before you commit — it is the one place in this migration where Redisson is behind. For workloads that do not span zones, or where replica reads are already pinned by other means, nothing here changes.

Post-Migration Hardening

Once traffic is stable, close out the operational work. Confirm TLS is enforced end to end and that you are using the valkeys:// scheme where appropriate. Re-apply ACLs and auth, including Entra ID if you use it. Review connection pool sizing against the new latency profile. If you run on Kubernetes, update readiness and liveness probes, Helm chart values and any hard-coded connection strings — see connecting Redisson to a Valkey cluster on Kubernetes.

One thing not to expect from this migration: a security improvement. Because the two projects share a codebase ancestry, they largely share a vulnerability surface. In July 2026, CVE-2026-23479 and CVE-2026-25243 were patched across both Redis 8.8 and the Valkey 9.1, 9.0 and 8.1 lines within the same window. This is a licensing and governance change, and it requires the same patching discipline afterwards as before.

Common Pitfalls

  • Assuming post-fork Redis features exist in Valkey. Redis 8.8's Array type and INCREX have no Valkey equivalent. Check anything you adopted after Redis 7.2.
  • Skipping the Lua audit. Redisson's module-free objects are built on EVAL, so on this architecture Lua compatibility is data-structure compatibility.
  • Upgrading the client and the engine together. See Step 3. This is the one way a "no code change" migration silently corrupts reads.
  • Missing a connection string. Helm charts, Kubernetes manifests, readiness probes, CI configs and Terraform variables all hold endpoints that your application config does not.
  • Trusting a typo'd URL error message. Redisson's validation error still reads "Redis url should start with redis:// or rediss://", so a malformed Valkey URL produces a message pointing you at the wrong scheme.
  • Version-gating on redis_version. Valkey reports redis_version:7.2.4 whatever its real version is. Redisson ignores that field; your own health checks and feature flags may not.
  • Decommissioning too early. A rollback path you deleted is not a rollback path.

Frequently Asked Questions

Is Valkey compatible with Redis?

Yes. Valkey was forked from Redis OSS 7.2.4 and maintains command and wire-protocol compatibility. Existing Redis clients, commands and RESP2/RESP3 connections work unchanged. Compatibility questions arise only around features Redis added after the fork, and around Redis Stack modules.

Do I need to change my Java code to migrate from Redis to Valkey?

In most cases, no. If your client supports Valkey, the migration is an infrastructure change and your application code is untouched. With Redisson you change the connection address — the valkey:// scheme is supported directly. Code changes are only needed if you depend on Redis Stack modules.

Can I use Jedis or Lettuce with Valkey?

Generally yes, since Valkey preserves the Redis wire protocol. Note that the Valkey project's recommended Java clients are Redisson, Valkey GLIDE and valkey-java; other clients supporting Redis OSS 7.2 are compatible but are not part of the tested set. Verify cluster topology discovery against your target Valkey version before cutover.

Does Valkey Sentinel work differently from Redis Sentinel?

No. The port is still 26379, the directive is still sentinel monitor <name> <ip> <port> <quorum>, the shipped default name is still mymaster, and the failover event a client subscribes to is still +switch-master. Valkey renamed the binary to valkey-sentinel but installs a redis-sentinel symlink by default and accepts either name, and it kept every legacy command spelling as an alias — which is why Redisson drives Valkey Sentinel with no Valkey-specific code. The one difference is an addition rather than a change: the replica redirect capability described above, which Redis does not have.

Does Redisson support Valkey?

Yes. Redisson supports Valkey and Redis from the same client and API, including the valkey://, valkeys:// and valkey+uds:// URL schemes, Valkey Cluster mode with database selection, and Valkey Sentinel. One client library covers both engines during and after migration, so you can roll back without swapping dependencies.

Will there be downtime?

Not necessarily. Cluster migrations can run with no downtime by adding Valkey nodes as replicas, letting them replicate, then promoting them. Standalone snapshot migration requires a brief pause; live replication does not. The path you choose determines the downtime, not the engine change itself.

Can I roll back a Redis to Valkey migration?

Yes, if you plan for it. Keep the source Redis instance running read-only through a validation window rather than decommissioning it at cutover. Because Redisson connects to both engines with the same API, rollback is a connection-string revert rather than a code change or redeployment.

What happens to my Redis Stack modules?

They need replacing. Valkey provides valkey-json, valkey-bloom and valkey-search as BSD-licensed modules, though search is a subset of RediSearch. RedisTimeSeries has no Valkey equivalent, but Redisson's RTimeSeries is module-free and closes that gap. Cuckoo filters, Top-K and T-Digest have no Valkey path at all.

Next Steps

If you are still deciding between the two engines, start with our Valkey vs Redis comparison. If the decision is made, the module audit is the first thing to run and the codec check is the first thing to plan around.

Redisson gives Java teams one client and one API across both engines, along with distributed locks, client-side caching, reliable queues and integrations for Spring Cache, Spring Session, Hibernate and JCache. Compare the PRO and Community Edition feature sets, or start a free trial.