Redis vs Valkey: API, Protocol and Data Format Compatibility
Short version: Redis and Valkey are still compatible at the API level. The same commands, the same RESP2 and RESP3 wire protocol, the same redis:// URLs, the same client libraries, the same Lua scripts, the same redis.conf. Where they are no longer compatible is the data format on disk and on the wire between servers. Valkey reads RDB files from Redis 7.2 and earlier, and refuses the RDB files Redis 7.4 and later write. Valkey 9 writes an RDB with a VALKEY080 signature that Redis rejects before it reads a single key. Everything that travels through a client is fine. Everything that travels as a dump, an AOF or a replication stream needs checking.
I run Layerbase, which hosts both Redis and Valkey, so I have a stake here. The compatibility facts below come from the two source trees and the vendors' own docs, and they stand whether or not you ever use us.
Versions as of September 2026: Valkey's current line is 9.1.2, released 2026-09-01, with 9.2.0-rc1 in test. Redis ships several supported lines, the newest being 8.10.x. Valkey forked from Redis 7.2.4 in March 2024, so every divergence below happened after that point.
Contents
- Compatibility at a glance
- The data format is where it actually breaks
- Replication between the two
- Wire protocol: RESP2 and RESP3
- Commands, Lua and functions
- Client libraries
- Modules are the clean break
- Config files, binaries and cluster
- Where they have diverged since the fork
- Licensing
- Testing your own dump against both
- When to pick which
- FAQ
Compatibility at a glance
| Area | Compatible? | Detail |
|---|---|---|
| Command API | Yes, for everything that existed at the fork | Both sides have added commands since. Anything in Redis 7.2 behaves the same on both. |
| Wire protocol | Yes | Both speak RESP2 and RESP3, both negotiate with HELLO. No divergence. |
| Connection URI | Yes | redis:// and rediss:// on port 6379 for both. |
| Client libraries | Yes | Standard Redis clients talk to Valkey unchanged. There is no separate protocol to implement. |
| RDB dump files | Partly, and this is the trap | Valkey reads RDB from Redis 7.2 and earlier. Redis 7.4+ and Valkey 9 each write a format the other refuses. |
DUMP / RESTORE payloads | Partly | The payload carries the same RDB version footer, so it inherits the same limits. |
| AOF | Follows RDB | An AOF with an RDB preamble carries the RDB constraint with it. |
Replication (REPLICAOF across) | Partly | Full sync ships an RDB, so it succeeds or fails on exactly the RDB rule above. |
| Lua scripts and functions | Yes | Same EVAL, EVALSHA and FUNCTION surface. Both have tightened sandboxing separately. |
| Cluster protocol | Yes in principle, no in practice | Do not mix the two inside one cluster. Nodes exchange RDB during slot moves. |
| Config file | Yes | Valkey reads a redis.conf as-is, and keeps the old directive names as aliases. |
| Binaries | Yes | make install creates redis-server and redis-cli symlinks to the Valkey binaries. |
| Module API | Mostly | Valkey accepts modules built against the Redis 7.2 RedisModule_ API. Redis 8's JSON and search are in core, not loadable modules, so they do not transfer. |
| License | Not a compatibility question | Redis 8+ is AGPLv3 / RSALv2 / SSPLv1. Valkey is BSD 3-Clause. |
The useful way to hold this: the client-facing surface is compatible, the server-facing surface is not. If your application only ever talks to the server through a client library, you can swap engines by changing a URL. The moment you move bytes between two servers, check the versions first.
The data format is where it actually breaks
This is the part the summaries skip, and it is the part that fails at 2am during a migration.
Both engines write RDB files that start with a 9-byte signature: five or six characters of magic followed by a zero-padded version number. A loading server checks the magic, then the version, then refuses anything it does not recognize. Here is what each release writes, read straight from src/rdb.h on each branch:
| Server | RDB version written | File signature |
|---|---|---|
| Redis 7.2.x | 11 | REDIS0011 |
| Redis 7.4.x, 8.0, 8.2, 8.4 | 12 | REDIS0012 |
| Redis 8.6.x | 13 | REDIS0013 |
| Redis 8.8.x | 14 | REDIS0014 |
| Redis 8.10.x | 15 | REDIS0015 |
| Valkey 7.2.x, 8.0.x, 8.1.x | 11 | REDIS0011 |
| Valkey 9.0.x, 9.1.x | 80 | VALKEY080 |
Two things fall out of that table.
Redis 7.4 and later write an RDB that Valkey will not load. Valkey's own migration guide says it plainly: Valkey "reads and writes RDB and AOF files compatible with Redis OSS 7.2", and "RDB files produced by Redis CE 7.4 and later are not compatible" (valkey.io/topics/migration). In the source, Valkey 9 reserves RDB versions 12 through 79 as a "foreign" range for formats it deliberately does not interpret, via RDB_FOREIGN_VERSION_MIN and RDB_FOREIGN_VERSION_MAX in src/rdb.h. That range is exactly where Redis has been incrementing since the fork.
There is an escape hatch, and I would not build a plan on it. Valkey has an rdb-version-check config, default strict, that can be set to relaxed. In relaxed mode it will attempt a REDIS-magic file in that range on a best-effort basis, and abort the moment it meets a type or opcode it does not recognize (Valkey 9 refuses type codes 22 through 243 from a Redis-magic file outright). It is a "try it and see" switch, not a compatibility guarantee. Treat a successful load as luck about which data types you happened to be using.
Valkey 9 writes an RDB that Redis will not load, and it fails earlier than you would expect. Valkey 9.0 changed its signature from REDIS0011 to VALKEY080, and the code comment says why: "RDB 11 is the last open-source Redis RDB version, used by Valkey 7.x and 8.x. RDB 12-79 are reserved for Redis non-compatible RDB formats. We start using high rdb version numbers since Valkey 9.0. This is in order to avoid collisions with non-OSS Redis RDB versions." Redis's loader does memcmp(buf, "REDIS", 5) and bails with "Wrong signature trying to load DB from file" if it does not match (src/rdb.c). So it is not a version mismatch error, it is a signature rejection. Third-party tools that parse RDB by hand hit the same wall.
The one pair that does work in both directions is Redis 7.2 and Valkey 8.x or earlier, because both write plain REDIS0011.
DUMP and RESTORE inherit all of this. The serialized payload has no magic string, just a trailing RDB version, so a DUMP taken from Redis 8.x carries version 12 and Valkey's strict check refuses it the same way. Same for an AOF written with an RDB preamble.
Replication between the two
A full sync ships an RDB. That is the whole answer.
Pointing a Valkey replica at a Redis 7.2 primary with REPLICAOF works, and Valkey's migration guide documents it as the zero-downtime path: attach the replica, let it sync, promote it, repoint your clients. It is genuinely the nicest way to leave Redis 7.2.
Pointing a Valkey 9 replica at a Redis 8.x primary does not work, because the full sync hands over an RDB version 12 through 15 payload and the replica refuses it. Pointing a Redis replica at a Valkey 9 primary does not work either, because the primary sends VALKEY080. If replication is your migration plan and you are on Redis 7.4 or later, the plan needs to change: dump and reload through a key-level copy, or run a scan-based copier that reads keys through the client protocol instead of moving RDB bytes.
This is also why I would not mix engines inside a single cluster. Slot migration moves data between nodes in RDB form, so a mixed cluster inherits every constraint above at the worst possible moment.
Wire protocol: RESP2 and RESP3
No divergence here, and this is the row people are usually asking about when they say "protocol compatibility".
Both engines speak RESP2 and RESP3, both negotiate the version with HELLO, and both default to RESP2 for a connection that never sends HELLO. Valkey's protocol spec is the Redis spec, kept in place: RESP3 is described as "a superset of RESP2", HELLO returns a map of server information, and an unsupported version gets a -NOPROTO error. A client that works against one works against the other at the byte level.
The one thing that reads differently is INFO, and it trips up monitoring. Valkey does not just report its own version, it also reports a fixed redis_version:7.2.4, forever, on every release. Its migration guide spells out the reason and the fix: the field exists "for backward compatibility", and you should "use server_name and valkey_version to detect the actual Valkey server and version". That value is pinned in the source, where src/version.h carries the comment that it "should never exceed 7.2.x".
So a dashboard that greps redis_version out of a Valkey 9.1 server will tell you it is running Redis 7.2.4. That is working as designed, and it is the single most misleading line in either server's output.
Commands, Lua and functions
Every command that existed in Redis 7.2 exists on both sides and behaves the same way. Strings, lists, sets, sorted sets, hashes, streams, pub/sub, transactions, expiry, SCAN, ACLs, EVAL, EVALSHA, FUNCTION: all shared ancestry, all unchanged.
Divergence is entirely additive, in both directions, and it is the part that creeps up on you two years after the fork:
- Redis 8 added vector sets (
VADD,VSIMand relatives), the first new data type in years, plus the former Redis Stack command families. Valkey has noV*commands in core. - Valkey 9.0 added atomic slot migration and numbered databases in cluster mode. Valkey 9.1 added
MSETEXandCLUSTERSCAN, described in the 9.1 release post. - Some things landed on both sides at different times, so do not treat them as a reason to pick one. Hash field expiration is the clearest case: Redis added
HEXPIRE,HTTL,HPERSIST,HGETEXandHGETDELin 7.4, Valkey added the same family in 9.0, and both have all of them today (I checkedsrc/commands.defon both). Atomic slot migration exists on both sides too, with different command surfaces. If a comparison table tells you hash field TTL is Valkey-only, it is out of date. - Both sides have reworked Lua sandboxing independently since the fork. A script that only uses
redis.calland standard Lua runs on both. A script relying on a specific sandbox escape or a deprecated API may not.
If you are writing code that must run on either, the safe subset is "what Redis 7.2 could do". That covers almost every cache, queue, session store and rate limiter I have seen.
Client libraries
Standard Redis clients work against Valkey without modification, because there is nothing new to implement. node-redis, ioredis, redis-py, go-redis, Jedis, Lettuce, redis-cli, BullMQ: all of them connect to Valkey and cannot tell the difference. Valkey did not invent a protocol, it kept one.
There is also an official Valkey client, Valkey GLIDE, a Rust core with Python, Java, Node.js and Go bindings (C# and PHP in preview, C++ and Ruby in development). Worth knowing what it declares: GLIDE supports Valkey 7.2, 8.0, 8.1 and 9.0, and Redis OSS 6.2, 7.0, 7.1 and 7.2. It does not claim support for Redis 8. So the official Valkey client is compatible with the Redis versions that predate the license change, which is a neat summary of the whole relationship.
Practical read: keep using the client you already have. Move to GLIDE only if you want its cluster and failover behaviour specifically, not for compatibility reasons.
Modules are the clean break
This is where compatibility ends completely, and no config flag helps.
Redis 8 folded the old Redis Stack technologies into core: "Integrating Redis Stack technologies, including JSON, Time Series, probabilistic data types, Redis Query Engine and more into core Redis 8 under AGPL", alongside the new vector sets data type. If you run Redis 8, JSON and search and time series are in the server, no module loading required.
Valkey keeps them as separate modules and ships them together in the valkey-bundle container image: valkey-json, valkey-bloom, valkey-search and valkey-ldap, on top of the server. valkey-search provides FT.CREATE, FT.DROPINDEX, FT.INFO, FT._LIST, FT.SEARCH and FT.AGGREGATE (valkey.io/topics/search), which are the same command names RediSearch used, though Valkey publishes no compatibility claim against RediSearch and you should not assume argument-for-argument parity.
The module API itself, though, is more compatible than the module ecosystem. Valkey says so directly: "Modules written for Redis OSS using the RedisModule_ API work in Valkey. Valkey also provides the ValkeyModule_ API and valkeymodule.h header for new modules" (migration guide). Valkey ships a src/redismodule.h that maps the legacy REDISMODULE_* names onto the new ones, described in its own header as a "Snapshot for Redis 7.2.4" with the caveat that "compatibility with future Redis versions is not guaranteed". So a third-party module written against the Redis 7.2 module API generally compiles and loads on Valkey.
What that does not get you is Redis 8's feature set. JSON, search, time series and probabilistic types are no longer distributed as loadable modules you could point Valkey at, because Redis 8 moved them into the server, and they are not BSD licensed. If you depend on RedisJSON, RediSearch, RedisTimeSeries or RedisBloom today, moving to Valkey means adopting Valkey's equivalents and revalidating behaviour. Scope it as a port, not a swap.
Config files, binaries and cluster
Small stuff, but it is what makes a swap feel like a non-event.
Valkey reads a redis.conf unchanged. Directive names carried over wholesale, and where Valkey renamed something it kept the old name as an alias: masterauth still works as an alias for primaryauth, slaveof for replicaof, slave-read-only for replica-read-only, hash-max-ziplist-entries for hash-max-listpack-entries. One to watch is the commandlog rework in Valkey 8, where slowlog-max-len became an alias of commandlog-slow-execution-max-len. Aliases work, but if you have config management that reads values back, it will read back the new names.
Binaries keep the old names too. Valkey's README notes that make install creates symlinks from redis-server, redis-cli and the rest to the Valkey binaries, and that you can turn this off with USE_REDIS_SYMLINKS=no. Init scripts and Dockerfiles that call redis-server keep working.
The cluster bus protocol has common ancestry, and valkey.io documents a deliberately temporary mixed cluster as a migration path: add Valkey nodes to an existing Redis cluster as replicas, promote one, retire the Redis nodes. That path is scoped to Redis OSS 7.2 and earlier, for the same reason as everything else here, since adding a replica requires a full sync. The bus itself is not publicly documented, and both projects have changed it since the fork, so treat a mixed cluster as a migration window measured in minutes and run one engine per cluster the rest of the time.
Where they have diverged since the fork
Beyond the data format, the interesting divergence is architectural.
Valkey went after throughput and cluster scale. Valkey 8 introduced async I/O threading and dual-channel replication. Valkey 9 added atomic slot migration, numbered databases in cluster mode, pipeline memory prefetching, zero-copy responses and multipath TCP. Valkey 9.1 redesigned the I/O threading model again and cut memory for short strings. That work is why AWS, Google and Oracle put engineers on it.
Redis went after features in the box. Redis 8 put JSON, search, time series and probabilistic types into core, added vector sets, and shipped a large batch of performance work. For a single node where you want more than key-value semantics without operating modules, that is a real lead.
Neither roadmap is going to converge back. Two years in, "Valkey is Redis with a different license" is no longer an accurate description of either project.
Licensing
Worth stating precisely, because it is half of why people are comparing these at all.
Redis 8 and later is tri-licensed: AGPLv3, RSALv2 or SSPLv1, at your choice (LICENSE.txt). AGPLv3 is OSI-approved, so Redis 8+ is open source by the definition that started the 2024 argument. That same file confirms the other half: "Redis Open Source 7.2 and prior releases remain subject to the BSDv3 clause license." Redis 7.4 through 7.x, released after the March 2024 change and before Redis 8, are SSPL/RSALv2 only with no AGPL option.
Valkey is BSD 3-Clause throughout, under the Linux Foundation, and has not changed.
The practical question for a legal review is narrow: do we allow AGPL dependencies? If yes, Redis 8 clears your policy. If no, or if you are building a platform that offers an in-memory store as a service, BSD is the one that clears it without a conversation. Running unmodified Redis behind your own application does not trigger the AGPL network clause, but plenty of legal teams ban AGPL outright rather than reason about where the boundary sits, and that is a policy call, not a technical one.
Testing your own dump against both
None of the above tells you whether your data moves. The compatibility rule is about format versions, and the only thing that settles it for your keyspace is trying it.
The quickest way to do that is to run both engines at once and point the same client, and the same dump, at each. Layerbase Cloud has Redis and Valkey on the same account and the same free tier, no card, so you can have both up in a couple of minutes. Two things to know before you use us as your test rig:
- Our Redis is 7.2, the last BSD release, which writes
REDIS0011. That is deliberate, and it means a dump taken from our Redis loads into Valkey cleanly. It also means we are not the place to reproduce a Redis 8 RDB failure. If you need to test against Redis 8.x specifically, run it yourself. - Our Valkey offers 9.0 by default and 8.0 if you ask for it, which is a useful pair on its own: 8.0 writes
REDIS0011and 9.0 writesVALKEY080, so you can see the signature change with your own keys.
Check what you are actually talking to before you conclude anything, and grep server_name, not redis_version:
redis-cli -u "$URL" INFO server | grep -E 'server_name|redis_version|valkey_version'Against our Valkey, all three lines come back from the same server, and only two of them are true:
server_name:valkey
valkey_version:9.0.5
redis_version:7.2.4Both databases branch, so you can fork a copy of a real dataset and try a destructive restore against the branch instead of the original. If you would rather do this on your own machine, the Layerbase CLI runs both engines locally with no Docker:
lbase create myredis -e redis --start
lbase create myvalkey -e valkey --startFor the full migration walkthrough, including the replication cutover and the scan-based copy for when replication is not an option, see Migrating from Redis to Valkey. If you are choosing a managed host rather than an engine, Redis Cloud alternatives and the Redis free tier comparison are the closer reads, and Valkey 9 on Layerbase covers what is in 9.0 specifically.
Where we are the wrong answer: if you need a multi-node cluster, multi-region replication, or Redis 8's in-core search and vector sets, we do not offer any of those and you should look elsewhere.
When to pick which
Pick Redis if your legal team allows AGPL, or if you want JSON, search, time series and vector sets in the server without operating modules. Redis 8 ships a bigger box than Valkey does.
Pick Valkey if your organization blocks copyleft, if you are building a platform that embeds an in-memory store, if you want governance no single vendor can reverse, or if your cloud provider has already standardized on it. It is also the side doing the throughput and cluster-scale engineering.
On compatibility grounds specifically: if you are on Redis 7.2 or earlier, moving to Valkey is close to free, and replication will carry your data across. If you are on Redis 7.4 or later, you have already crossed the data-format line, and moving in either direction is a key-level copy rather than a file move. That is the real cost of waiting, and it is worth knowing before you plan the window rather than during it.
FAQ
Are Valkey and Redis compatible in API, protocol and data format?
At the API and protocol level, yes: identical command semantics for everything that existed in Redis 7.2, the same RESP2 and RESP3 wire protocol negotiated with HELLO, and the same client libraries and redis:// URLs. The data format is where they split. Valkey reads RDB files from Redis 7.2 and earlier only, Redis 7.4 and later write RDB version 12 and up which Valkey's strict version check refuses, and Valkey 9 writes a VALKEY080 signature that Redis rejects on the magic string before reading any keys.
Can Valkey read a Redis RDB file?
Only from Redis 7.2 and earlier, which write REDIS0011. Valkey's own migration guide states that RDB files from Redis CE 7.4 and later are not compatible, and the source reserves RDB versions 12 through 79 as a foreign range it will not interpret. There is a relaxed setting for rdb-version-check that will attempt one anyway and abort on the first unrecognized type, which is a diagnostic tool rather than a migration path.
Can Redis read a Valkey RDB file?
From Valkey 8.x and earlier, yes, because those write REDIS0011 exactly like Redis 7.2. From Valkey 9, no. Valkey 9 writes a VALKEY080 signature, and Redis checks for the literal string REDIS before anything else, so it fails with "Wrong signature trying to load DB from file".
Can a Valkey server replicate from a Redis server?
From Redis 7.2 and earlier, yes, and it is the documented zero-downtime migration: attach with REPLICAOF, let it sync, promote, repoint clients. From Redis 7.4 or later, no, because the full sync ships an RDB in a version Valkey refuses. The reverse (a Redis replica of a Valkey 9 primary) fails for the same reason in the other direction.
Do I need a different client library for Valkey?
No. Every standard Redis client works against Valkey unchanged, because the wire protocol is the same one. There is an official client, Valkey GLIDE, if you want it, but it is an option rather than a requirement, and it declares support for Redis OSS only up to 7.2.
What are the technical differences between Valkey and Redis in 2026?
Core data structures and the protocol are shared. The differences are: Redis 8 has JSON, search, time series, probabilistic types and vector sets in core, which Valkey keeps as separate modules (valkey-json, valkey-bloom, valkey-search, valkey-ldap). Valkey has numbered databases in cluster mode and several rounds of I/O threading, replication and throughput work. The RDB format has diverged in both directions, and Valkey pins redis_version:7.2.4 in INFO forever. Licenses differ: Redis 8+ is AGPLv3 / RSALv2 / SSPLv1, Valkey is BSD 3-Clause. Hash field expiration and atomic slot migration are on both sides now, so neither is a differentiator.
Is Valkey still a drop-in replacement for Redis?
For an application talking to the server through a client, yes: change the URL and nothing else. For an operator moving data between servers, no longer, unless the Redis side is 7.2 or earlier. The phrase "drop-in replacement" was accurate in 2024 and is now accurate only about the client-facing half.
Wrapping up
The compatibility story has three layers, and mixing them up is what causes the bad afternoon. Clients and protocol: compatible, and likely to stay that way, because neither project gains anything by breaking RESP. Commands: compatible for the shared 7.2 ancestry, additive on both sides since. Data format: diverged, in both directions, with Redis 7.4 as the line on one side and Valkey 9 as the line on the other.
If you are planning a move, the first thing to check is not the license. It is which RDB version your current server writes. Create a Valkey database alongside your existing one and try the restore before you schedule the window.
Keep reading
- Redis Cloud alternatives: pay for the modules, or stop paying for themRedis Cloud prices itself around the module story: search, JSON, time series, vector sets, Active-Active. If you use those, the bill is buying something real. If you use Redis as a cache, a session store, or a queue, you are paying the module premium for a key-value store. Here is what each tier buys, where a flat plan fits, and when to stay.
- Build the Redis backend for a WhatsApp botConversation state with TTLs, BullMQ queues for scheduled reminders, idempotency keys for retried webhooks, and per-recipient rate limits, all on one Redis-compatible Valkey.
- Migrating from Vercel KV to LayerbaseVercel KV was sunset and its stores moved to Upstash Redis, so the move is a data copy and a one-line client swap. Paste the rediss:// string behind your project Storage tab and copy every key, type, and TTL into flat-priced managed Redis or Valkey.
- Migrating from Upstash to LayerbaseUpstash bills per request, which is great at zero traffic and surprising at scale. Here is how to move to flat-priced managed Valkey on Layerbase: copy every key with one API key, and swap the REST client for a standard Redis driver.