Specify a Read Strategy
By default, Valkey GLIDE directs read commands to the primary node that owns a specific slot. For applications that prioritize read throughput and can tolerate possibly stale data, Valkey GLIDE provides the flexibility to route reads to replica nodes.
Valkey GLIDE provides support for the following read strategies, allowing you to choose the one that best fits your specific use case.
Available Read Strategies
Section titled “Available Read Strategies”The table describes ordinary cluster reads. Candidate nodes belong to the key’s shard; “local” means the client’s configured availability zone (AZ). Writes continue to go to the primary. See command routing for the standalone fallback difference.
| Strategy | Description |
|---|---|
| Primary (Default) | Always read from primary, in order to get the freshest data. |
| All Nodes | Rotate reads across available primary and replica connections, without an AZ preference. |
| Prefer Replica | Spread requests between all replicas in a round robin manner. If no replica is available, route the requests to the primary. |
| AZ Affinity | Spread the read requests between replicas in the same client’s availability zone in a round robin manner, falling back to other available replicas, then to the primary only if no replica is available. |
| AZ Affinity Replicas and Primary | Spread the read requests among nodes within the client’s availability zone in a round robin manner, prioritizing local replicas, then the local primary, and falling back to other available replicas, then to the primary only if no replica is available. |
| AZ Affinity All Nodes | Spread the read requests equally among all nodes (primary and replicas) within the client’s availability zone in a round robin manner, falling back to a round robin across all nodes if no node in the client’s availability zone is available. |
All Nodes
Section titled “All Nodes”Use All Nodes to share reads between the primary and replicas without preferring an AZ. This strategy is available in Java, Python, Node, and Go in 2.4.0 and later. It does not require a client AZ.
from glide import ( GlideClusterClient, GlideClusterClientConfiguration, NodeAddress, ReadFrom)
addresses = [NodeAddress(host="address.example.com", port=6379)]client_config = GlideClusterClientConfiguration(addresses, read_from=ReadFrom.ALL_NODES)
client = await GlideClusterClient.create(client_config)await client.set("key1", "val1")# get rotates across available primary and replicas for the key's shardawait client.get("key1")import glide.api.GlideClusterClient;import glide.api.models.configuration.GlideClusterClientConfiguration;import glide.api.models.configuration.NodeAddress;import glide.api.models.configuration.ReadFrom;
GlideClusterClientConfiguration config = GlideClusterClientConfiguration.builder() .address(NodeAddress.builder() .host("address.example.com") .port(6379) .build()) .readFrom(ReadFrom.ALL_NODES) .build();GlideClusterClient client = GlideClusterClient.createClient(config).get();
client.set("key1", "val1").get();
// get rotates across available primary and replicas for the key's shardclient.get("key1").get();import {GlideClusterClient} from "@valkey/valkey-glide";
const addresses = [ { host: "address.example.com", port: 6379 }];
const client = await GlideClusterClient.createClient({ addresses: addresses, readFrom: "allNodes"});await client.set("key1", "val1");// get rotates across available primary and replicas for the key's shardawait client.get("key1");import ( "context"
glide "github.com/valkey-io/valkey-glide/go/v2" "github.com/valkey-io/valkey-glide/go/v2/config")
func ConnectClusterWithReadStrategyAllNodes() { myConfig := config.NewClusterClientConfiguration(). WithAddress(&config.NodeAddress{Host: "address.example.com", Port: 6379}). WithReadFrom(config.ReadFromAllNodes)
client, _ := glide.NewClusterClient(myConfig)
client.Set(context.Background(), "key1", "val1")
// Get rotates across available primary and replicas for the key's shard client.Get(context.Background(),"key1")}Prefer Replica
Section titled “Prefer Replica”from glide import ( GlideClusterClient, GlideClusterClientConfiguration, NodeAddress, ReadFrom)
addresses = [NodeAddress(host="address.example.com", port=6379)]client_config = GlideClusterClientConfiguration(addresses, read_from=ReadFrom.PREFER_REPLICA)
client = await GlideClusterClient.create(client_config)await client.set("key1", "val1")# get will read from one of the replicasawait client.get("key1")import glide.api.GlideClusterClient;import glide.api.models.configuration.GlideClusterClientConfiguration;import glide.api.models.configuration.NodeAddress;import glide.api.models.configuration.ReadFrom;
GlideClusterClientConfiguration config = GlideClusterClientConfiguration.builder() .address(NodeAddress.builder() .host("address.example.com") .port(6379) .build()) .readFrom(ReadFrom.PREFER_REPLICA) .build();GlideClusterClient client = GlideClusterClient.createClient(config).get();
client.set("key1", "val1").get();
// get will read from one of the replicasclient.get("key1").get();import {GlideClusterClient} from "@valkey/valkey-glide";
const addresses = [ { host: "address.example.com", port: 6379 }];
const client = await GlideClusterClient.createClient({ addresses: addresses, readFrom: "preferReplica"});await client.set("key1", "val1");// get will read from one of the replicasawait client.get("key1");import ( "context"
glide "github.com/valkey-io/valkey-glide/go/v2" "github.com/valkey-io/valkey-glide/go/v2/config")
func ConnectClusterWithReadStrategyPreferReplica() { myConfig := config.NewClusterClientConfiguration(). WithAddress(&config.NodeAddress{Host: "address.example.com", Port: 6379}). WithReadFrom(config.PreferReplica)
client, _ := glide.NewClusterClient(myConfig)
client.Set(context.Background(), "key1", "val1")
// Get will read from one of the replicas client.Get(context.Background(),"key1")}using Valkey.Glide;using static Valkey.Glide.ConnectionConfiguration;
var config = new ClusterClientConfigurationBuilder() .WithAddress("address.example.com", 6379) .WithReadFrom(new ReadFrom(ReadFromStrategy.PreferReplica)) .Build();
await using var client = await GlideClusterClient.CreateClient(config);await client.SetAsync("key1", "val1");
// GetAsync will read from one of the replicasawait client.GetAsync("key1");$addresses = [ ['host' => 'address.example.com', 'port' => 6379]];
$client = new ValkeyGlideCluster( addresses: $addresses, read_from: ValkeyGlide::READ_FROM_PREFER_REPLICA);
$client->set('key1', 'val1');// get will read from one of the replicas$client->get('key1');require "valkey"
client = Valkey.new( nodes: [{ host: "address.example.com", port: 6379 }], cluster_mode: true, read_from: Valkey::ReadFrom::PREFER_REPLICA)
client.set("key1", "val1")# get will read from one of the replicasclient.get("key1")AZ Affinity
Section titled “AZ Affinity”When using the AZ Affinity read strategy, the clientAz setting is required to ensure that readonly commands are directed to replicas within the specified availability zone if they exist. Reads fall back to other available replicas, then to the primary only if no replica is available.
from glide import ( GlideClusterClient, GlideClusterClientConfiguration, NodeAddress, ReadFrom)
addresses = [NodeAddress(host="address.example.com", port=6379)]client_config = GlideClusterClientConfiguration(addresses, read_from=ReadFrom.AZ_AFFINITY, client_az="us-east-1a")
client = await GlideClusterClient.create(client_config)await client.set("key1", "val1")# get will read from one of the replicas in the same client's availability zone if they existawait client.get("key1")import glide.api.GlideClusterClient;import glide.api.models.configuration.GlideClusterClientConfiguration;import glide.api.models.configuration.NodeAddress;import glide.api.models.configuration.ReadFrom;
GlideClusterClientConfiguration config = GlideClusterClientConfiguration.builder() .address(NodeAddress.builder() .host("address.example.com") .port(6379) .build()) .readFrom(ReadFrom.AZ_AFFINITY) .clientAZ("us-east-1a") .build();GlideClusterClient client = GlideClusterClient.createClient(config).get();
client.set("key1", "val1").get();
// get will read from one of the replicas in the same client's availability zone if they existclient.get("key1").get();import {GlideClusterClient} from "@valkey/valkey-glide";
const addresses = [ { host: "address.example.com", port: 6379 }];
const client = await GlideClusterClient.createClient({ addresses: addresses, readFrom: "AZAffinity", clientAz: "us-east-1a",});await client.set("key1", "val1");// get will read from one of the replicas in the same client's availability zone if they existawait client.get("key1");import ( "context"
glide "github.com/valkey-io/valkey-glide/go/v2" "github.com/valkey-io/valkey-glide/go/v2/config")
func ConnectClusterWithReadStrategyAZAffinity() { myConfig := config.NewClusterClientConfiguration(). WithAddress(&config.NodeAddress{Host: "address.example.com", Port: 6379}). WithReadFrom(config.AzAffinity). WithClientAZ("us-east-1a")
client, _ := glide.NewClusterClient(myConfig)
client.Set(context.Background(), "key1", "val1")
// Get will read from one of the replicas in the same client's availability zone if they exist client.Get(context.Background(),"key1")}using Valkey.Glide;using static Valkey.Glide.ConnectionConfiguration;
var config = new ClusterClientConfigurationBuilder() .WithAddress("address.example.com", 6379) .WithReadFrom(new ReadFrom(ReadFromStrategy.AzAffinity, "us-east-1a")) .Build();
await using var client = await GlideClusterClient.CreateClient(config);await client.SetAsync("key1", "val1");
// GetAsync will read from one of the replicas in the same client's availability zone if they existawait client.GetAsync("key1");$addresses = [ ['host' => 'address.example.com', 'port' => 6379]];
$client = new ValkeyGlideCluster( addresses: $addresses, read_from: ValkeyGlide::READ_FROM_AZ_AFFINITY, client_az: 'us-east-1a');
$client->set('key1', 'val1');// get will read from one of the replicas in the same client's availability zone if they exist$client->get('key1');require "valkey"
client = Valkey.new( nodes: [{ host: "address.example.com", port: 6379 }], cluster_mode: true, read_from: Valkey::ReadFrom::AZ_AFFINITY, client_az: "us-east-1a")
client.set("key1", "val1")# get will read from one of the replicas in the same client's availability zone if they existclient.get("key1")AZ Affinity Replicas and Primary Read Strategy
Section titled “AZ Affinity Replicas and Primary Read Strategy”When using the AZ Affinity Replicas and Primary read strategy, the clientAz setting is required to ensure that readonly commands are directed to replicas or the primary within the specified availability zone if they exist. In cluster mode, reads prefer local replicas, then the local primary, then any available replica, and use the primary only when no replica is available. If the only available local node is the primary, it receives reads even when remote replicas are available.
In standalone mode, the final fallback instead rotates across all available primary and replica nodes. Local replicas still take priority over the local primary.
from glide import ( GlideClusterClient, GlideClusterClientConfiguration, NodeAddress, ReadFrom)
addresses = [NodeAddress(host="address.example.com", port=6379)]client_config = GlideClusterClientConfiguration(addresses, read_from=ReadFrom.AZ_AFFINITY_REPLICAS_AND_PRIMARY, client_az="us-east-1a")
client = await GlideClusterClient.create(client_config)await client.set("key1", "val1")# get prefers local replicas, then the local primary, then remote replicas, then the primaryawait client.get("key1")import glide.api.GlideClusterClient;import glide.api.models.configuration.GlideClusterClientConfiguration;import glide.api.models.configuration.NodeAddress;import glide.api.models.configuration.ReadFrom;
GlideClusterClientConfiguration config = GlideClusterClientConfiguration.builder() .address(NodeAddress.builder() .host("address.example.com") .port(6379) .build()) .readFrom(ReadFrom.AZ_AFFINITY_REPLICAS_AND_PRIMARY) .clientAZ("us-east-1a") .build();GlideClusterClient client = GlideClusterClient.createClient(config).get();
client.set("key1", "val1").get();
// get prefers local replicas, then the local primary, then remote replicas, then the primaryclient.get("key1").get();import {GlideClusterClient} from "@valkey/valkey-glide";
const addresses = [ { host: "address.example.com", port: 6379 }];
const client = await GlideClusterClient.createClient({ addresses: addresses, readFrom: "AZAffinityReplicasAndPrimary", clientAz: "us-east-1a",});await client.set("key1", "val1");// get prefers local replicas, then the local primary, then remote replicas, then the primaryawait client.get("key1");import ( "context"
glide "github.com/valkey-io/valkey-glide/go/v2" "github.com/valkey-io/valkey-glide/go/v2/config")
func ConnectClusterWithReadStrategyAZAffinityReplicaAndPrimary() { myConfig := config.NewClusterClientConfiguration(). WithAddress(&config.NodeAddress{Host: "address.example.com", Port: 6379}). WithReadFrom(config.AzAffinityReplicaAndPrimary). WithClientAZ("us-east-1a")
client, _ := glide.NewClusterClient(myConfig)
client.Set(context.Background(), "key1", "val1")
// Get prefers local replicas, then the local primary, then remote replicas, then the primary client.Get(context.Background(),"key1")}using Valkey.Glide;using static Valkey.Glide.ConnectionConfiguration;
var config = new ClusterClientConfigurationBuilder() .WithAddress("address.example.com", 6379) .WithReadFrom(new ReadFrom(ReadFromStrategy.AzAffinityReplicasAndPrimary, "us-east-1a")) .Build();
await using var client = await GlideClusterClient.CreateClient(config);await client.SetAsync("key1", "val1");
// GetAsync prefers local replicas, then the local primary, then remote replicas, then the primaryawait client.GetAsync("key1");$addresses = [ ['host' => 'address.example.com', 'port' => 6379]];
$client = new ValkeyGlideCluster( addresses: $addresses, read_from: ValkeyGlide::READ_FROM_AZ_AFFINITY_REPLICAS_AND_PRIMARY, client_az: 'us-east-1a');
$client->set('key1', 'val1');// get prefers local replicas, then the local primary, then remote replicas, then the primary$client->get('key1');require "valkey"
client = Valkey.new( nodes: [{ host: "address.example.com", port: 6379 }], cluster_mode: true, read_from: Valkey::ReadFrom::AZ_AFFINITY_REPLICAS_AND_PRIMARY, client_az: "us-east-1a")
client.set("key1", "val1")# get prefers local replicas, then the local primary, then remote replicas, then the primaryclient.get("key1")AZ Affinity All Nodes
Section titled “AZ Affinity All Nodes”When using the AZ Affinity All Nodes read strategy, the clientAz setting is required to ensure that readonly commands are spread equally across all nodes (primary and replicas) within the specified availability zone if they exist. Unlike AZ Affinity Replicas and Primary, the local primary is an equal member of the rotation rather than a fallback, so it shares reads even when local replicas are available. If no local node is available, reads rotate across all available primary and replica nodes for the key’s shard, including a remote primary even when remote replicas are available.
Compared with AZ Affinity Replicas and Primary in cluster mode:
- A local primary shares reads while local replicas are also available.
- If no local node is available, a remote primary shares reads with remote replicas.
- If the only available local node is the primary, both strategies use it; this case is unchanged.
Standalone clients use the same local-first, all-node rotation. However, including the primary in the final fallback pool is already the behavior of standalone AZ Affinity Replicas and Primary. See command routing for the comparison.
from glide import ( GlideClusterClient, GlideClusterClientConfiguration, NodeAddress, ReadFrom)
addresses = [NodeAddress(host="address.example.com", port=6379)]client_config = GlideClusterClientConfiguration(addresses, read_from=ReadFrom.AZ_AFFINITY_ALL_NODES, client_az="us-east-1a")
client = await GlideClusterClient.create(client_config)await client.set("key1", "val1")# get will read from one of the nodes (primary or replicas) in the same client's availability zone if they existawait client.get("key1")import glide.api.GlideClusterClient;import glide.api.models.configuration.GlideClusterClientConfiguration;import glide.api.models.configuration.NodeAddress;import glide.api.models.configuration.ReadFrom;
GlideClusterClientConfiguration config = GlideClusterClientConfiguration.builder() .address(NodeAddress.builder() .host("address.example.com") .port(6379) .build()) .readFrom(ReadFrom.AZ_AFFINITY_ALL_NODES) .clientAZ("us-east-1a") .build();GlideClusterClient client = GlideClusterClient.createClient(config).get();
client.set("key1", "val1").get();
// Rotate across local primary and replicas; if none are available,// rotate across all available primary and replicas for the key's shard.client.get("key1").get();