As of today, when establishing a connection to a replica without readonly mode, it is redirecting all commands to the primary node by returning MOVED error.
But keyless commands (which marked as READONLY) do get executed on the replica, even if those type of command extract key information, and can return stale data.
This creates inconsistent behavior: some operations fail over to the primary, while others proceed on the replica with potentially outdated information.
Example output:
127.0.0.1:6379> readwrite
OK
127.0.0.1:6379> get a
(error) MOVED 15495 172.19.117.208:6380
127.0.0.1:6379> hgetall p3
(error) MOVED 3689 172.19.117.208:6380
127.0.0.1:6379> FT.SEARCH idx "*=>[KNN 1 @description $query_vector]" PARAMS 2 query_vector "\xcd\xccL?\x00\x00\x00\x00\x00\x00\x00\x00" DIALECT 2
1) (integer) 1
2) "p3"
3) 1) "__description_score"
2) "0.0399999953806"
3) "description"
4) "\x00\x00\x80?\x00\x00\x00\x00\x00\x00\x00\x00"
127.0.0.1:6379> scan 0
1) "0"
2) 1) "p3"
2) "p2"
3) "p1"
4) "p5"
5) "a"
6) "p4"
This example shows that running hgetall on a key returns MOVED error, but running ft.search (which is a valkey-search command) returns that same value.
Also SCAN command worked and returned information about the keys.
I believe those type of commands needs to be treated the same as other readonly commands that include keys.
Proposed Solution
The proposed solution is a new opt-in client capability: CLIENT CAPA redirect-keyless.
When a client declares this capability, keyless read commands (those marked CMD_READONLY with no key specs and not CMD_MOVABLE_KEYS) on a replica will return a -MOVED redirect to the primary, consistent with how keyed reads behave. If the replica is READONLY, keyless reads continue to execute locally on the replica, since the client has explicitly opted into replica reads.
This capability is independent of the existing CLIENT CAPA redirect and requires no changes to COMMAND INFO metadata or client-side routing tables — the server handles the redirect decision entirely. Non-read keyless commands (e.g., PING, INFO) are unaffected.
Affected client libraries
Here is a summary of how clients currently handle -REDIRECT error both in CMD and CME:
┌──────────────────┬────────────────────────────────────────┬────────────────────────────────────────────────────────────────────────────────────┬──────────────────────────────────────┬─────────────────────────────────────────────────────┐
│ Client │ Sends `CLIENT CAPA redirect` in CMD? │ Handles `-REDIRECT` in CMD? │ Sends `CLIENT CAPA redirect` in CME? │ Handles `-REDIRECT` in CME? │
├──────────────────┼────────────────────────────────────────┼────────────────────────────────────────────────────────────────────────────────────┼──────────────────────────────────────┼─────────────────────────────────────────────────────┤
│ **valkey-java** │ Yes (by default) │ Only with explicit `RedirectCommandExecutor` setup; default `JedisPooled` does not │ Yes (by default) │ Yes — retries on target node, no slot cache refresh │
│ **valkey-go** │ Yes (when `EnableRedirect=true`) │ Yes — swaps primary connection │ No (never sent in CME) │ No — not checked in cluster path │
│ **valkey-glide** │ No │ No │ No │ No │
│ **valkey-py** │ Yes (when `client_capa_redirect=True`) │ No — parsed as `RedirectError` but never caught │ No (filtered out in cluster mode) │ No — uncaught exception │
│ **iovalkey** │ No │ No │ No │ No │
│ **libvalkey** │ No │ No │ No │ No │
└──────────────────┴────────────────────────────────────────┴────────────────────────────────────────────────────────────────────────────────────┴──────────────────────────────────────┴─────────────────────────────────────────────────────┘
Draft solution: #3505
As of today, when establishing a connection to a replica without
readonlymode, it is redirecting all commands to the primary node by returning MOVED error.But keyless commands (which marked as READONLY) do get executed on the replica, even if those type of command extract key information, and can return stale data.
This creates inconsistent behavior: some operations fail over to the primary, while others proceed on the replica with potentially outdated information.
Example output:
This example shows that running
hgetallon a key returns MOVED error, but runningft.search(which is a valkey-search command) returns that same value.Also
SCANcommand worked and returned information about the keys.I believe those type of commands needs to be treated the same as other
readonlycommands that include keys.Proposed Solution
The proposed solution is a new opt-in client capability:
CLIENT CAPA redirect-keyless.When a client declares this capability, keyless read commands (those marked CMD_READONLY with no key specs and not CMD_MOVABLE_KEYS) on a replica will return a
-MOVEDredirect to the primary, consistent with how keyed reads behave. If the replica is READONLY, keyless reads continue to execute locally on the replica, since the client has explicitly opted into replica reads.This capability is independent of the existing
CLIENT CAPA redirectand requires no changes to COMMAND INFO metadata or client-side routing tables — the server handles the redirect decision entirely. Non-read keyless commands (e.g., PING, INFO) are unaffected.Affected client libraries
Here is a summary of how clients currently handle -REDIRECT error both in CMD and CME:
Draft solution: #3505