Zero-Downtime Migration from Redis to Valkey — How to Switch Your Backend Service Without Code Changes
When Redis Inc. announced the switch from the BSD license to SSPL/RSALv2 in March 2024, I was honestly caught off guard. I imagine a lot of people fired off messages to their legal teams asking, "Could this put commercial restrictions on our service?" I certainly did.
Here's the good news: if you're on Redis 7.2 or below, you can migrate to Valkey right now without changing a single line of code. Valkey is a project forked from Redis 7.2.4 by the Linux Foundation, permanently maintained under the BSD-3-Clause license. Because it preserves the RESP protocol and RDB file format, your existing clients and data don't need to be touched. With 17 vendors backing it — AWS, Google Cloud, Oracle, ByteDance, and more — the governance story is solid too.
In this post, we'll walk through which Redis versions support which migration paths to Valkey, and the concrete steps to switch a production service with zero downtime, with code examples. The examples are in Node.js, but the core flow applies equally to Python or Java.
Core Concepts
Why Valkey Is Essentially the Same as Redis
There's a reason migrating to Valkey is simpler than you might expect. Because the fork starts from Redis 7.2.4, backward compatibility is well-maintained from the protocol level down to the data files.
| Item | Details |
|---|---|
| Wire protocol | Supports both RESP2 / RESP3 → existing Redis clients work by changing only the connection address |
| Data files | Fully compatible with RDB/AOF file formats from Redis OSS 7.2 and below |
| Caveat | Data files generated by Redis Community Edition 7.4 or above cannot be read directly |
RESP (REdis Serialization Protocol) — the communication protocol between Redis and its clients. Because Valkey supports RESP2/RESP3 identically, existing clients like
ioredis,redis-py,Jedis, andStackExchange.Rediswork normally with just a connection address change.
Your Current Redis Version Determines Migration Difficulty
The first thing to check is your current Redis version.
redis-cli INFO server | grep redis_version- Redis OSS 7.2 or below → The easiest case. You can bring data files over as-is.
- Redis CE 7.4 or above → The data file format has changed, so direct copy won't work. You'll need to use replication for live synchronization.
- Redis Stack / Enterprise → You'll need to resolve dependencies on proprietary modules like RedisJSON, RediSearch, and vector search first. This requires migration planning beyond a simple switchover.
It's also worth checking in advance which commands are not supported in Valkey. If you're using Redis purely for core caching or sessions, you'll be fine — but if you're using module commands like JSON.SET / FT.SEARCH / TS.ADD, you'll need alternatives. You can check each command you use with redis-cli COMMAND DOCS <command>.
Performance Has Actually Improved
I was initially skeptical — "Can a fork really outperform the original?" — but the numbers convinced me. The key improvement is a rebuild of the internal hash structure using Swiss Tables, which offers better cache hit rates than traditional hash tables, reducing memory access overhead. The gap becomes noticeably wider starting with Valkey 8.1.
| Version | Key Improvements |
|---|---|
| Valkey 8.1 (2025.03) | +8% throughput, -22% P99 latency, -20% memory |
| Valkey 9.0 (2025.10) | +40% throughput, per-field TTL for hashes, 100M+ RPS clusters |
| Valkey 9.1 (2026.05) | ~2.1M RPS, additional -10% memory |
The figures above are sourced from the Valkey official blog and Better Stack benchmarks (2025–2026). Actual results may vary depending on workload and instance specs.
Practical Application
Example 1: Snapshot Method — Dev Environments or Services That Allow a Brief Maintenance Window
If a short service interruption is acceptable or your data volume is small, moving the RDB file directly is the simplest approach. I used this method to validate things in our dev environment first.
# 1. Create a background snapshot on Redis
redis-cli BGSAVE
# Verify completion — done when rdb_bgsave_in_progress is 0
# (LASTSAVE only returns a timestamp and should not be used to determine completion)
redis-cli INFO persistence | grep rdb_bgsave_in_progress
# 2. Copy the RDB file to the Valkey data directory
cp /var/lib/redis/dump.rdb /var/lib/valkey/dump.rdb
# 3. Start the Valkey server
valkey-server /etc/valkey/valkey.conf
# 4. Validate data
# KEYS "*" blocks the single thread — never use it on a production server
# Use SCAN instead to safely sample keys
valkey-cli DBSIZE
valkey-cli SCAN 0 COUNT 20| Step | Command | Checkpoint |
|---|---|---|
| Create snapshot | BGSAVE |
Confirm rdb_bgsave_in_progress: 0 in INFO persistence |
| Copy file | cp dump.rdb |
Verify file size and permissions are identical |
| Validate data | DBSIZE + SCAN |
Compare key count with the original Redis DBSIZE |
Example 2: Replication Method — Zero-Downtime Switchover for Production Services
This is the most common scenario in practice. If you're running something like a session cache or game leaderboard where even a brief downtime is unacceptable, this is the right approach. Valkey acts as a replica of Redis, synchronizing data live, then gets promoted to primary when ready.
# [On the Valkey server] Set Redis as the primary and start replication
valkey-cli REPLICAOF <redis-host> 6379
# Monitor replication status in real time
watch -n 2 "valkey-cli INFO replication | grep -E 'role|master_link_status|master_sync'"When master_link_status: up and master_sync_in_progress: 0, live synchronization is running stably.
# [After confirming sync completion] Promote Valkey to standalone primary
valkey-cli REPLICAOF NO ONEAfter promotion, switch your application connections to Valkey. Since you only need to swap an environment variable or DNS CNAME, it's important not to shut down the Redis server immediately at this point — keep it running. If something goes wrong right after the switch, just revert the environment variable back to the original Redis host and you've rolled back. No code redeployment needed.
# Pre-traffic-switch checklist
# 1. master_sync_in_progress: 0 (sync complete)
# 2. master_link_status: up (connection maintained)
# 3. Redis server still running (standby for rollback)For Sentinel / Cluster setups: Teams using Sentinel need an additional step: attach the Valkey replica, then update Sentinel configuration to point to the Valkey primary. Cluster mode typically uses a rolling replacement approach, node by node. Detailed procedures for each setup are available in the Valkey official migration docs.
Example 3: Node.js Application — Client Code Stays the Same
If you're already using ioredis, all you really need to change is the connection address. This is one of Valkey's biggest advantages. In practice, Redis hosts are usually managed via environment variables, so there's exactly one change point.
import Redis from 'ioredis';
const client = new Redis({
host: process.env.REDIS_HOST ?? 'valkey.internal', // just change the environment variable
port: Number(process.env.REDIS_PORT ?? 6379),
});
// None of the usage code below needs to be touched
await client.set('session:abc', JSON.stringify(sessionData), 'EX', 3600);
const data = await client.get('session:abc');There's also Valkey GLIDE, the official Valkey client. Written in Rust, it offers more stable connection pool management and auto-reconnection than ioredis, and supports cluster mode without additional configuration. If you've experienced intermittent connection drops with ioredis, GLIDE is worth considering.
import { GlideClient } from '@valkey/valkey-glide';
const client = await GlideClient.createClient({
addresses: [{ host: process.env.VALKEY_HOST ?? 'valkey.internal', port: 6379 }],
});
await client.set('key', 'value');
const val = await client.get('key');
await client.close();If you primarily use Python or Java, redis-py and Jedis both work with just a connection address swap. Python and Java bindings for GLIDE are available at valkey-glide GitHub.
Pros and Cons Analysis
Our team's biggest concern was advanced module dependencies, but since most of our usage was for session caching, we ultimately made the transition without much friction. The table below covers the items we actually weighed during that process.
Pros
| Item | Details |
|---|---|
| Permanently open source | BSD-3-Clause, managed by the Linux Foundation. No license change risk |
| Performance gains | Up to 40% throughput improvement over Redis OSS, 20–30% memory reduction |
| Cloud cost | AWS ElastiCache for Valkey is 20% cheaper per hour, adopted as the default for new instances |
| Client compatibility | Use existing libraries like ioredis, redis-py, Jedis without code changes |
| Ecosystem | Supported by 17 vendors including AWS, Google Cloud, Oracle, and Alibaba Cloud |
Cons and Caveats
| Item | Details | Mitigation |
|---|---|---|
| No advanced modules | No RedisJSON, RediSearch, vector search, or time series | Consider alternative modules or Google Memorystore (includes vector search) |
| CE 7.4+ incompatibility | Cannot directly port data files from newer Redis CE | Use replication method for live migration |
| Module command differences | Module commands like JSON.*, FT.*, TS.* are unsupported |
Audit used commands with COMMAND DOCS before switching |
SSPL (Server Side Public License) — a license first introduced by MongoDB that requires source disclosure even when the software is offered as a service. For SaaS operators, it effectively acts as a commercial restriction. Valkey's BSD-3-Clause carries no such restrictions.
To be honest, Valkey isn't the right choice for every team. Teams using Redis Enterprise or those where vector search is a core feature need to evaluate their service requirements first. The migration effort could end up exceeding the license cost savings.
The Most Common Mistakes in Practice
- Skipping the Redis version check — I made this mistake myself early on. I thought "just copying the RDB file should do it" and tried loading Redis CE 7.4 data into Valkey — it couldn't read the file at all. That one line,
redis-cli INFO server | grep redis_version, can save you hours later. - Insufficient audit of module command dependencies — If you're using modules like
RedisJSONorRediSearch, those commands don't exist in Valkey. When we actually listed the commands our team was using, we were surprised by how many places were using module commands — far more than expected. I strongly recommend pulling a list of your used commands before switching. - Switching traffic before replication sync completes — Running
REPLICAOF NO ONEwhilemaster_sync_in_progress: 1can result in partial data loss. Our team actually missed this timing once and had some keys disappear, so I strongly recommend visually confirming it's0before proceeding.
Closing Thoughts
Just running a single version-check command right now is enough to get started. If you're on Redis 7.2 or below, you can attempt the migration in your dev environment today and gain both license security and performance improvements at the same time.
Three steps you can take right now:
- Check your version and module dependencies first. Use
redis-cli INFO server | grep redis_versionto find your current version, and check whether you're using modules likeRedisJSONorRediSearch. - Try the snapshot method in your dev environment first. Spin up Valkey with
docker run valkey/valkey:latest, copy the RDB file, and verifyDBSIZEand key samples. - For production, use the replication method. Attach Valkey as a replica with
REPLICAOF, confirmmaster_sync_in_progress: 0viaINFO replication, then promote withREPLICAOF NO ONE. Keep the Redis server running as a rollback standby.
References
- Valkey Official Migration Docs | valkey.io
- Valkey GLIDE Official Client | GitHub
- Percona: Redis to Valkey Migration Guide | Percona Docs
- Aiven: Migrating 15,000 Redis Servers to Valkey | Aiven Blog
- AWS ElastiCache for Valkey Migration Best Practices | AWS Blog
- Redis vs Valkey 2026 In-Depth Comparison | Better Stack
- Valkey 2025 Year in Review | Valkey Official Blog
- Valkey Official GitHub Repository | GitHub
- Google Cloud Memorystore for Valkey Official Docs | Google Cloud