Redis to Valkey: A Single-Writer Migration Plan
Last edited on August 2, 2026

The dangerous moment in a Redis-to-Valkey migration is not installing the new binary. It is the interval when two servers could accept different writes, while a green PING makes the change look finished. A safe VPS migration proves the source is compatible, rehearses the target with real application behavior, creates one controlled writer boundary, and keeps the old Redis process from quietly becoming a second primary.

Valkey is designed as a vendor-neutral continuation of Redis OSS, but “compatible” needs a version boundary. Valkey’s official migration guide supports Redis OSS 7.2 and earlier data, protocol and configuration formats. Redis Community Edition 7.4 and later produces data files that Valkey does not accept through that documented path. Read the running source before choosing any command.

First gate: identify what is actually running

Capture the source version, role, persistence state, keyspace, memory policy and active clients from the instance itself. Do not rely on an old package ticket or a container tag that may have been updated.

redis-cli -h <redis-private-host> -p 6379 INFO server
redis-cli -h <redis-private-host> -p 6379 INFO replication
redis-cli -h <redis-private-host> -p 6379 INFO persistence
redis-cli -h <redis-private-host> -p 6379 INFO keyspace
redis-cli -h <redis-private-host> -p 6379 CONFIG GET maxmemory maxmemory-policy appendonly appendfsync save databases

Use the approved authentication and TLS options for your environment without placing a password in shell history. Save the output in a restricted change record because client names, addresses and configuration details can reveal infrastructure.

The migration path in this article fits a standalone Redis OSS 7.2-or-earlier primary. Stop and design a separate plan when the source is Redis CE 7.4+, a Redis Cluster, Sentinel-managed failover, a module-dependent workload or a managed service whose provider controls replication. Wire compatibility does not prove that a module, Lua script or provider extension behaves the same.

Target selection deserves the same care. Choose a maintained Valkey release that your operating system or container policy supports, then read its release notes. Moving from an old Redis version and jumping several Valkey major versions in one maintenance window increases the number of variables. A same-family rehearsal may produce clearer evidence than a migration combined with a large feature upgrade.

Pick one migration path

There are two practical routes for a standalone instance. Choose from downtime tolerance and write activity, not from which command list looks shorter.

Path Useful when Main risk Required control
Fresh RDB snapshot A maintenance window can stop writers and the dataset loads within the window Writes arriving after the final snapshot Quiesce every writer before the snapshot and keep Redis stopped afterward
Valkey replica cutover Write downtime must be short and the source can replicate privately to Valkey Lag or writes crossing the promotion boundary Observe catch-up, fence writers, stop Redis, then promote exactly once

Snapshot cutover gives the clearest boundary

A physical migration is easy to reason about. Quiesce applications and workers, create a fresh snapshot, confirm rdb_last_bgsave_status:ok, stop Redis, copy the completed RDB into a separate Valkey data directory, and start Valkey against that copy. Keep a second protected copy outside both live directories.

If AOF will be enabled on Valkey, follow the current Valkey persistence procedure rather than switching a configuration line and hoping the restart imports the RDB. The official documentation warns that an incorrect RDB-to-AOF transition can lose data. Wait for the AOF rewrite status to finish successfully before treating persistence as durable.

Replication shortens the writer pause

For an eligible source, Valkey can start as a read-only replica of Redis. That lets the bulk transfer happen while Redis still serves traffic. Replication is asynchronous, however, so “connected” is not the same as “caught up.”

Valkey replica:
  REPLICAOF <redis-private-host> 6379

Observe until stable:
  INFO replication

Required signals before the writer fence:
  role:slave
  master_link_status:up
  master_sync_in_progress:0
  replication offsets no longer show material lag

Configure replication authentication and TLS through reviewed files or secret storage. Never expose port 6379 broadly just to make the migration easy. The source and target should communicate over a private network or a tightly controlled encrypted path with narrow firewall rules.

Write the acceptance contract before rehearsal

Key counts are useful, but they are not a complete test. Expired keys may disappear between observations, multiple logical databases can have different counts, and an application can fail even when every key arrived. Define the evidence that will close the change.

Evidence What to compare or prove Failure means
Identity Source version is eligible; target reports Valkey and the intended release Stop before data movement
Keyspace Per-database keys and expiry counts are explainably close at the same writer boundary Find missing writes, wrong database selection or expiry drift
Persistence Last RDB/AOF operation is successful and target survives a controlled restart Do not cut over
Policy maxmemory, eviction policy, database count and timeout settings match the workload decision Correct target configuration and rehearse again
Application Cache, session, queue, lock, rate-limit or primary-data workflows pass synthetic tests Investigate client, command, Lua or module compatibility
Operations Metrics, logs, backup and restore path identify Valkey correctly Monitoring or recovery is not ready

Choose synthetic records that are safe to create and easy to remove through the application. Include a normal value, a value with a TTL, and any critical data type the workload uses. A session store should prove login and expiry. A queue should prove enqueue, reserve, acknowledge and retry behavior. A distributed lock should prove acquisition, contention and release. Primary-data use demands stricter reconciliation than a disposable cache.

Record baseline latency, operations per second, connected clients, used memory, evictions, rejected connections and error rate during representative load. These numbers are not a benchmark contest; they help distinguish a migration regression from an old problem that already existed.

Rehearse on an isolated Valkey node

Restore a recent snapshot or attach a temporary Valkey replica in a network where production clients cannot discover it. A rehearsal should use the same persistence mode, memory ceiling, eviction policy, authentication method and client library versions planned for production.

Compare state without exposing data

Capture INFO keyspace, INFO persistence, INFO memory and the relevant configuration values on both sides. Avoid pasting full key names or values into public tickets. Where sensitive data is involved, record counts, status fields and hashes generated by an approved application-level verifier instead.

Restart the rehearsal target once. A target that works only from memory has not passed a persistence test. Confirm the expected databases return, the last persistence status remains healthy and application probes still succeed after restart.

Exercise semantics the protocol cannot guarantee

Run the application’s own integration suite or a controlled smoke test. Pay special attention to Lua scripts, transactions, pipelines, Pub/Sub, streams, client-side caching, keyspace notifications, ACL users, TLS, modules, blocking commands and timeout behavior. Existing Redis clients generally speak the same RESP protocol, but a successful socket connection does not validate every command path.

Test memory pressure deliberately in staging if eviction matters. A different maxmemory-policy can turn the same dataset into unexpected evictions or write failures. Also leave fork headroom for RDB creation or AOF rewrite; a dataset that fits in steady state may still stress a small VPS during persistence work.

Make recovery part of the rehearsal

Create a fresh backup from Valkey and restore it into another isolated directory. Confirm the application can read the restored state. A replica is not a backup: replication faithfully copies accidental deletes and harmful writes.

The cutover: keep exactly one writer

Schedule a window with a named operator, a communication channel and authority to abort. Lowering a DNS TTL does not help when applications use a fixed private address, a service name or a long-lived connection pool, so document how every client discovers Redis.

Freeze, catch up, stop, promote

For a replica migration, use this order:

  1. Stop or pause every application, worker and scheduled job that can write to Redis.
  2. Confirm new write traffic has stopped at the source.
  3. Wait until the Valkey replica reports a healthy link, no full sync in progress and negligible offset lag.
  4. Stop the Redis source while the writer fence still exists.
  5. Promote Valkey once with REPLICAOF NO ONE and confirm it reports the primary role.
  6. Update the application secret, service-discovery record or connection endpoint.
  7. Start one low-risk client and run the acceptance contract before releasing the rest.

Do not promote Valkey while Redis remains a writable production endpoint. Asynchronous replication reduces downtime, but it cannot decide which of two later writes should win.

Move clients in controlled groups

Release clients by workload rather than all at once: a read-heavy service, then one writer, then workers and scheduled jobs. Watch application errors, Valkey logs, latency, connected clients, memory, evictions and persistence status after each group.

valkey-cli -h <valkey-private-host> -p 6379 INFO server
valkey-cli -h <valkey-private-host> -p 6379 INFO replication
valkey-cli -h <valkey-private-host> -p 6379 INFO persistence
valkey-cli -h <valkey-private-host> -p 6379 INFO stats
valkey-cli -h <valkey-private-host> -p 6379 INFO memory

Check server_name and valkey_version rather than relying only on the backward-compatible redis_version field. Keep the source Redis service disabled and its old endpoint blocked from application networks during the observation period.

Rollback is a data decision, not a DNS flip

Before Valkey accepts a new production write, rollback can be simple: stop the test client, keep Valkey isolated and restore application access to the unchanged Redis source. After Valkey accepts writes, the old Redis copy is stale. Pointing clients back would discard or fork the new history.

That moment is the rollback boundary. Beyond it, recovery may require fixing Valkey in place, restoring a known-good backup, or planning a controlled reverse data migration whose compatibility has been tested. Do not restart the old source as a writable primary merely because it is familiar.

Preserve the pre-cutover snapshot, source configuration, version inventory and client map for the approved retention window. Preserve them as recovery evidence, not as a second live service. If the workload cannot tolerate this rollback boundary, build a topology-specific migration with rehearsed bidirectional or dual-write reconciliation rather than improvising during the incident.

FAQ

These are the three questions operators most often need to resolve before approving the change.

Can every Redis release move to Valkey from its data files?

No. The official Valkey path covers Redis OSS 7.2 and earlier. Redis Community Edition 7.4 and later data files are not compatible with that method, so verify the source and use a separately tested migration route.

Does matching DBSIZE prove the migration worked?

No. Counts can differ because of expirations and say nothing about values, TTLs, scripts, modules or application behavior. Compare per-database state at a writer boundary and run workload-specific acceptance tests.

Can the old Redis server stay online for fast rollback?

It can remain preserved but should not remain a reachable writer. Once Valkey accepts new writes, the old dataset is stale and a connection-string rollback can create loss or split-brain behavior.

Close the change after proof, not hope

Keep an observation window long enough to include normal traffic, scheduled jobs, expiry cycles, persistence work and a backup. The final evidence bundle should show one writable primary, the intended Valkey version, successful application probes, stable memory and eviction behavior, healthy persistence, a restorable backup and no clients reaching the retired Redis endpoint.

Capacity also matters during migration. A database-ready VPS host needs room for the dataset, copy-on-write during snapshots, AOF rewrite, logs and a protected backup staging area—not just enough RAM for the current used_memory value. If nobody owns the maintenance window, monitoring or recovery test, consider a managed hosting service before moving a critical data path.

Only then remove the old endpoint from discovery and schedule source decommissioning under normal change control. The goal is not to make Valkey answer PONG; it is to make the application, data and recovery story agree that the migration is complete.

Leave a Reply

Your email address will not be published. Required fields are marked *