You upgraded a Valkey 8.1 replica to 9.1, failed over, and now want to go back. The obvious fallback is to start the old 8.1 binary on the current dump.rdb. That file was rewritten by 9.1, so 8.1 logs Can't handle RDB format version 80 and exits. Valkey 9.0 moved its snapshot format to a new numbering: 7.2 to 8.x write RDB version 11, 9.0 and 9.1 write version 80, and the 9.2 release candidates write 81. Older binaries refuse newer files by default, and the setting that relaxes this works on a best-effort basis only. This post maps what each release writes and loads, how mixed-version replication behaves, and a rollback plan you can test before you need it.
- Valkey 7.2 to 8.x write RDB 11 (file header
REDIS0011), 9.0 and 9.1 write RDB 80 (VALKEY080), and the 9.2 release candidates write RDB 81. The first 9 bytes of a file tell you which one you have. - Valkey 7.2 and 8.0 cannot load a 9.x file at all. Valkey 8.1 can try with
rdb-version-check relaxed, and the load stops at the first type it does not know, such as a hash with field TTLs. - A 9.1 primary sends RDB 11 to 7.2 and 8.x replicas during a full sync, so one old-version replica can stay attached as a rollback target. A 9.0 primary always sends RDB 80.
- Upgrade to 9.1.3 or later, never 9.1.0 to 9.1.2: those releases read listpack entries of three exact sizes differently from 9.0, which breaks loads and replication between the two (PR #4819).
- Rollback stays a failover until the first 9.x-only feature is used. After that, it means a logical copy or a restore that loses recent writes.
Scope and review date: November 2026. This post covers self-managed Valkey 7.2, 8.0, 8.1, 9.0, and 9.1 (latest patches 7.2.15, 8.0.12, 8.1.11, 9.0.7, and 9.1.3), with notes on the 9.2.0-rc2 release candidate and on Redis CE 7.4 and later. Version numbers, defaults, and log strings were checked against the Valkey source code, valkey.conf, and release notes on 10 November 2026. The commands were not run in a lab, so rehearse them on staging.
Which RDB version does each Valkey release write?
Every RDB file starts with a 9-byte header: a magic string followed by the format version. The comment in src/rdb.h at 9.1.3 states the history directly: "RDB 11 is the last open-source Redis RDB version, used by Valkey 7.x and 8.x." Valkey 9.0 jumped to version 80 "to avoid collisions with non-OSS Redis RDB versions", and files above version 79 use the magic string VALKEY instead of REDIS.
The 9.2.0-rc1 and 9.2.0-rc2 tags set RDB_VERSION to 81, which adds a new hash type (type 23) and an opcode used by forkless full sync. Treat RDB 81 as release-candidate behaviour until 9.2.0 ships.
# The first 9 bytes are the magic string and the RDB version
head -c 9 /var/lib/valkey/dump.rdb; echo
# REDIS0011 written by Valkey 7.2 to 8.x, or Redis OSS 7.2 and earlier
# VALKEY080 written by Valkey 9.0 or 9.1
# VALKEY081 written by a Valkey 9.2 release candidateInterpretation: the header decides which binaries can start reading the file. A 9.2 release candidate set to rdbcompression lz4 or zstd writes a compressed stream that starts with VCS, and the 9.2 valkey.conf marks both codecs "Supported by Valkey 9.2 and later". The default, rdbcompression yes, still means per-string LZF.
What each Valkey line writes and can load
Switch lines to see which snapshot files a binary accepts with the default strict check
Valkey 7.2 and 8.x
| Question | Valkey 7.2 and 8.x |
|---|---|
| RDB version written | 11 |
| File header | REDIS0011 |
| Loads RDB 11 | Yes |
| Loads RDB 80 or 81 | 7.2 and 8.0: no. 8.1: only with relaxed, best effort |
| Loads Redis CE 7.4+ files (RDB 12 and up) | No, even with relaxed |
rdb-version-check | 8.1 only, default strict; absent in 7.2 and 8.0 |
Valkey 9.0 and 9.1
| Question | Valkey 9.0 and 9.1 |
|---|---|
| RDB version written | 80 |
| File header | VALKEY080 |
| Loads RDB 11 | Yes |
| Loads RDB 80 or 81 | 80: yes. 81: only with relaxed, best effort, uncompressed files only |
| Loads Redis CE 7.4+ files (RDB 12 and up) | Only with relaxed, and only if every type is one Valkey knows |
rdb-version-check | Default strict |
Valkey 9.2 release candidate
| Question | Valkey 9.2.0-rc2 |
|---|---|
| RDB version written | 81 |
| File header | VALKEY081, or VCS with lz4 or zstd compression |
| Loads RDB 11 | Yes |
| Loads RDB 80 or 81 | Yes |
| Loads Redis CE 7.4+ files (RDB 12 and up) | Only with relaxed, and only if every type is one Valkey knows |
rdb-version-check | Default strict |
Lead: the version only moves forward. An older binary reads a newer file only when you opt in, and only if the file holds nothing that binary has never seen.
Why are RDB versions 12 to 79 treated as Redis formats?
After Redis changed its license, Redis CE kept numbering its own format from 12. Per src/rdb.h in the redis/redis repository, Redis 7.4 to 8.4 write RDB 12, 8.6 writes 13, 8.8 writes 14, and 8.10 writes 15. Those formats add types Valkey does not have, and some reuse numbers that Valkey assigned differently. Type 22 is a Valkey 9.0 hash with field TTLs, but a Redis 7.4 release-candidate hash with a different layout. Opcode 243 is a Valkey slot import record, but Redis key metadata.
Valkey 8.1 reserved versions 12 to 79 as "foreign" in PR #1604 and refuses them even in relaxed mode. Valkey 9.0.0-rc2 added PR #2543, which accepts a foreign version in relaxed mode but rejects any type or opcode from 22 to 243 in a file with the REDIS header.
Constant in 9.1.3 rdb.h | Value | Meaning |
|---|---|---|
RDB_VERSION | 80 | The version this binary writes |
RDB_FOREIGN_VERSION_MIN / MAX | 12 / 79 | Versions reserved for "Redis non-compatible RDB formats" |
RDB_FOREIGN_TYPE_MIN / MAX | 22 / 243 | Types and opcodes refused in a foreign file |
RDB_VERSION_MAP | {11, 7.2.0}, {80, 9.0.0} | Which Valkey release introduced each version |
What does rdb-version-check relaxed actually do?
The setting arrived in Valkey 8.1.0. It takes strict or relaxed, defaults to strict, and can be changed at runtime. The 9.1.3 valkey.conf describes it as "a best-effort basis" and says "loading is aborted if unknown information is encountered", adding that it "also applies to replication and the RESTORE command."
In 8.1, relaxed accepts a VALKEY header with a higher version and fails on the first unknown type ("Unknown RDB encoding type"). In 9.0 and 9.1, it also accepts foreign Redis versions, and an unknown type ends the load with "Unknown type or opcode when loading DB. Unrecoverable error, aborting now."
valkey-cli CONFIG GET rdb-version-check
valkey-cli CONFIG SET rdb-version-check relaxedInterpretation: CONFIG SET is enough for a replica that is about to full sync or for RESTORE. A file loaded at startup is read before you can connect, so for that case the value has to be in the config file.
# valkey.conf on the Valkey 8.1 host you might roll back to
rdb-version-check relaxedWithout it, this is what the old binary logs when it meets a 9.x snapshot. The strings are from the 8.1.11 and 8.0.12 source.
grep -E "RDB format|signature|Fatal error loading" /var/log/valkey/valkey.log
# Valkey 8.1 with the default strict check:
# # Can't handle RDB format version 80
# # Fatal error loading the DB, check server logs. Exiting.
# Valkey 8.0 or 7.2 (no setting can change this):
# # Wrong signature trying to load DB from fileInterpretation: the 8.0 and 7.2 loaders only recognise a REDIS header, so they stop before the version is even read. On 8.1, relaxed gets past the header, and success then depends on what the data contains.
Identifying a 9.1 snapshot before you plan a rollback
Illustrative output: valkey-check-rdb 9.1.3 on a 9.1 dump; offsets and counts are examples
Read the header, not the verdict: the 9.1 checker passes its own format. VALKEY080 means only 9.0 or later can load the file, or 8.1 with relaxed if no 9.x-only types are present.
What happens to replication in a mixed-version rolling upgrade?
The Valkey releases page says to "always upgrade replicas before upgrading primaries", and that across major versions "data replicated from primaries to replicas will always be sent in a backward compatible format." The first half is easy: a 9.x replica of an 8.x primary loads the RDB 11 full sync without any setting. The second half depends on the primary's release.
- A 9.0 primary always writes RDB 80 with the
VALKEYheader; the 9.0.7 replication code has no per-replica version choice. A 7.2 or 8.0 replica cannot full sync from it, and an 8.1 replica can only try withrelaxed. - A 9.1 or later primary includes PR #2735, which "allows latest Valkey to send snapshots as RDB 11 to replicas running Valkey 7.2 and 8.x". The primary uses the version the replica announces and streams the older format over the socket, so its own
dump.rdbstays at version 80. - The exception: per the same PR, "if any new features that the replica can't handle (such as hash-field expiration and atomic slot migration) are in use, the full sync is aborted". The primary logs "Can't store key ... in RDB version 11".
A partial resync after a failover sends no RDB at all, only commands. The risk then moves to the command stream: an 8.x replica cannot run HSETEX or HEXPIRE. With the default propagation-error-behavior ignore, it logs the error, skips the command, and quietly diverges from the primary.
# Which release is each node really running? redis_version is always 7.2.4
for h in cache-01 cache-02 cache-03; do
echo "$h $(valkey-cli -h "$h" INFO server | grep '^valkey_version:' | tr -d '\r')"
doneInterpretation: every Valkey reports redis_version:7.2.4, as the migration guide notes, so only valkey_version shows the real release.
# On the 9.1 primary: does any data or traffic need a 9.x replica?
valkey-cli INFO keyspace
# example: db0:keys=18240,expires=3115,avg_ttl=412000,keys_with_volatile_items=0
valkey-cli INFO commandstats \
| grep -E 'cmdstat_(hsetex|hgetex|hexpire|hpexpire|hexpireat|hpexpireat|hgetdel|msetex|delifeq):'Interpretation: in 9.1, keys_with_volatile_items above 0 means hashes with field TTLs exist, and an RDB 11 full sync to an 8.x replica will abort. Any cmdstat_ line means a command added in 9.0 or 9.1 ran since the counters were last reset, and an 8.x replica could not apply it.
Rolling upgrade from Valkey 8.1 to 9.1.3, and the point of no return
Steps 1 to 3 keep a failover rollback open; step 4 closes it
Point of no return: it is the first 9.x-only write, not the binary swap. Hold back hash field TTLs, the new 9.0 and 9.1 commands, and slot migrations until you decide not to roll back.
Which 9.0 and 9.1 patch releases break cross-version loads?
Three 2026 fixes matter when versions are mixed. The most serious is PR #4819, shipped in 9.1.3 and 9.2.0-rc2. For listpack entries whose encoded length is exactly 16383, 2097151, or 268435455 bytes, two widths of the trailing length field are valid. Per the PR, "Valkey wrote the wider form up to 9.0 and the narrower one in 9.1.0 through 9.1.2", and each side misreads the other. The PR notes these lengths are reachable in normal use: a 16378-byte string element produces an entry length of exactly 16383.
| Fix | Affected | Fixed in | Symptom |
|---|---|---|---|
| #4819 listpack length field | 9.1.0 to 9.1.2 | 9.1.3 | RDB load and replication failures between 9.0 and 9.1 |
| #4105 replica version on the dual-channel RDB connection | 9.x replicas before 9.0.5 and 9.1.1 using dual-channel replication | 9.0.5, 9.1.1 | The primary sends RDB 11, and full syncs of hashes with field TTLs fail |
#4739 valkey-check-aof and the VALKEY signature | 9.0 and 9.1 tools before the fix | 9.0.7, 9.1.3 | A valid multi-part AOF with an RDB 80 base is reported as invalid |
The practical rule: go from 8.x or 9.0 straight to 9.1.3 or later. If a node already ran 9.1.0 to 9.1.2, move it forward to 9.1.3, which reads both widths, rather than back to 9.0. For which patch each branch needs for security fixes as well, see our Valkey support windows and minimum safe patch post.
# Check an AOF directory with a patched tool (9.0.7, 9.1.3 or later)
valkey-check-aof /var/lib/valkey/appendonlydir/appendonly.aof.manifest
# The base file of a multi-part AOF is an RDB file when aof-use-rdb-preamble is yes
head -c 9 /var/lib/valkey/appendonlydir/appendonly.aof.*.base.rdb; echoInterpretation: with aof-use-rdb-preamble yes (the default), a 9.x AOF base file starts with VALKEY080, so an AOF does not help an 8.x rollback either. An older valkey-check-aof that flags that file as invalid is the #4739 bug, not corruption.
Can you downgrade from Valkey 9 to Valkey 8?
There is no documented downgrade procedure, only three ways to move data back:
- Start the old binary on the new files. Only 8.1 with
relaxedcan try, as above. - Replicate into an old-version node. Works from a 9.1 or later primary until 9.x-only data exists.
- DUMP and RESTORE, or MIGRATE. The payload footer carries RDB version 80, which 8.x refuses under
strict.
# MIGRATE uses DUMP and RESTORE, so the payload says RDB 80
valkey-cli -h cache-new MIGRATE cache-old 6379 "" 0 5000 KEYS session:42
# (error) ERR Target instance replied with error: ERR DUMP payload version or checksum are wrongInterpretation: setting rdb-version-check relaxed on an 8.1 target lets RESTORE accept version 80 payloads for the old types. Keys in 9.x-only encodings still fail. A copy that reads values with ordinary commands and writes them back avoids the format entirely, but you handle each type and TTL yourself.
An RDB 11 snapshot taken before the upgrade always loads on the old version, but it holds nothing written after it was taken. Decide in advance how much loss is acceptable and whether you can replay writes from the application side.
Can Valkey load an RDB file from Redis 7.4 or later?
Officially, no. The Valkey migration guide says "Redis Community Edition (CE) version 7.4 and later produce data files that are not compatible with Valkey" and supports file migration only from Redis OSS 2.x to 7.2.x. Since 9.0, relaxed mode accepts the foreign header and loads the file if every type is one Valkey understands, but many Redis files still fail. Redis 7.4 and later write hashes with field TTLs as types 24 and 25. Redis 8.6 and later write every stream as type 26 and can write key metadata as opcode 243. All fall inside the refused 22 to 243 range, and the load ends with "Can't handle foreign type or opcode". Valkey 8.1 refuses these files outright.
# Test a Redis CE snapshot with the Valkey 9.1 checker before planning around it
head -c 9 redis-dump.rdb; echo # REDIS0012 from Redis 7.4 to 8.4
valkey-check-rdb redis-dump.rdbInterpretation: for a foreign file, the 9.1 checker prints "Foreign RDB version 12 detected" and, if it parses every key, "RDB looks OK, but loading requires config 'rdb-version-check relaxed'". We have not run this against Redis files, so treat a pass as a reason to try a staging load, not as proof. Replication from Redis CE 7.4 or later sends the same format, so a logical copy is the dependable route. Our Redis 8 vs Valkey 8 in production covers the feature differences you will meet on the way.
How do you upgrade Valkey with a rollback path you have tested?
The plan below targets a primary with replicas, managed by Sentinel or by hand, moving from 8.x to 9.1.3. It relies on PR #2735, so the new primary must be 9.1 or later. A 9.0 primary would cut the old replica off at its next full sync.
Upgrade from Valkey 8.x to 9.1.3 with a tested rollback
Eight steps; steps 5 and 7 are short write pauses during failover
-
Record versions and features in use
Note
valkey_versionon every node and check that no node runs 9.1.0 to 9.1.2.valkey-cli -h cache-01 INFO server \ | grep '^valkey_version:' -
Take an RDB 11 snapshot and test it
Copy it off the host and load it on a spare node of the old version. This is the last-resort backup.
valkey-cli -h cache-01 BGSAVE head -c 9 /var/lib/valkey/dump.rdb; echo -
Upgrade replicas to 9.1.3, one at a time
Restart each on the new binary and wait for the link to come back before the next one.
valkey-cli -h cache-02 INFO replication \ | grep '^master_link_status:' -
Keep one replica on the old version
This is the rollback target. Under Sentinel, give it a higher replica-priority value than the new nodes; Sentinel prefers the lowest, and 0 means never.
-
Fail over to a 9.1.3 replica
Write pauseUse FAILOVER on a standalone primary, or SENTINEL FAILOVER under Sentinel.
valkey-cli -h cache-01 FAILOVER \ TO cache-02 6379 TIMEOUT 5000 -
Burn in with no 9.x-only features
On the old replica, confirm an RDB 11 full sync finished. Keep field TTLs and the new commands off.
grep "sync: Finished with success" \ /var/log/valkey/valkey.log -
If needed, fail back to the old replica
RollbackPromote the old-version replica (under Sentinel, give it the lowest priority value first), then reattach or downgrade the 9.1.3 nodes.
valkey-cli -h cache-02 FAILOVER \ TO cache-03 6379 TIMEOUT 5000 -
Commit: upgrade the last replica
Only now enable hash field TTLs, the new commands, and slot migrations.
Rollback point: until the first 9.x-only write or step 8, rolling back is a failover. After that, it is a logical copy or the step 2 snapshot, which loses every write since it was taken.
The FAILOVER command waits for the named replica to catch up, then swaps roles; with TIMEOUT and no FORCE, it rolls back the attempt if the replica is too slow. During step 6, run the commandstats check above daily.
# Optional, on the old-version rollback replica only: stop on a command it
# cannot apply instead of skipping it and drifting from the primary
propagation-error-behavior panic-on-replicasInterpretation: with the default ignore, a rollback target that missed writes looks healthy until you promote it. A stopped replica is at least visibly unusable.
The releases page says it is "not recommended to run a Valkey cluster with servers running on different minor versions", and an old-version replica per shard is exactly that. An atomic slot migration in use also aborts RDB 11 full syncs. In cluster mode, keep the mixed window short and slot moves off, or make the rollback target a separate old-version cluster fed by a logical copy.
Frequently asked questions
Can Valkey 8 read a Valkey 9 RDB file?
Not by default. Valkey 9.0 and 9.1 write RDB version 80 with a VALKEY header. Valkey 7.2 and 8.0 reject that header outright. Valkey 8.1 rejects it under the default strict check, and with rdb-version-check set to relaxed it tries on a best-effort basis, aborting on any type it does not know, such as a hash with field TTLs.
What does rdb-version-check relaxed do in Valkey?
It lets a Valkey 8.1 or later server try to load an RDB file, replication stream, or RESTORE payload written in a newer format. Since 9.0 it also accepts Redis RDB versions 12 to 79 when every type is one Valkey knows. Loading still aborts at the first unknown type or opcode. The default is strict.
Can I import a Redis 8 RDB file into Valkey?
Valkey's migration guide says Redis CE 7.4 and later files are not compatible. Valkey 9.0 and later can attempt them with rdb-version-check relaxed, but the load fails on hashes with field TTLs and, from Redis 8.6, on streams. Test with valkey-check-rdb and a staging load, and plan a logical copy as the dependable path.
Can a Valkey 8 replica follow a Valkey 9 primary?
From a 9.1 or later primary, yes, with limits. The primary sends 7.2 and 8.x replicas a full sync in RDB 11, but aborts it if hashes with field TTLs or atomic slot migration are in use. Commands added in 9.0 or 9.1 cannot run on the replica. A 9.0 primary always sends RDB 80.
Which Valkey 9.1 patch should I upgrade to?
Use 9.1.3 or later. Releases 9.1.0 to 9.1.2 handle listpack entries of three exact lengths differently from 9.0, which causes RDB load and replication failures between the two lines. Valkey 9.1.3, released on 26 October 2026, fixes this and also carries a security fix for cluster Pub/Sub.
Key takeaways
- Read the first 9 bytes of any snapshot:
REDIS0011loads everywhere,VALKEY080needs 9.0 or later, or 8.1 withrelaxed. rdb-version-check relaxedis a best-effort escape hatch that stops at the first unknown type, not a downgrade feature.- Upgrade replicas first, go straight to 9.1.3 or later, and keep one old-version replica attached to the 9.1 primary as the rollback target.
- The point of no return is the first 9.x-only write: hash field TTLs, new 9.0 and 9.1 commands, or slot migrations.
- Redis CE 7.4 and later files are officially incompatible; plan a logical copy for them.
Plan a Valkey upgrade you can undo with JusDB
JusDB's Valkey migration team can review your versions, topology, and the 9.x features your applications plan to use, then write a replica-first upgrade runbook with a rollback replica and rehearse the failover and the rollback on staging.
Bring your INFO server and INFO replication output from each node, your persistence settings, and your maintenance windows. Your team approves every production change.