You spread nine Valkey nodes across three availability zones, set availability-zone on each one, and expect a zone outage to cost you one failover. Then us-east-1a goes dark and every surviving node logs Cluster state changed: fail, because valkey-cli --cluster create made the first three nodes you listed, all in that zone, the primaries. In every GA release up to 9.1.3, availability-zone is a label the server reports to clients. Nothing on the server reads it when it places replicas, counts failover votes, or picks the replica to promote. This guide covers what 8.0, 8.1, 9.1 and the 9.2 release candidate added, how to place nodes yourself, how Sentinel and Cluster rank replicas, what must survive a zone loss, and checklists for 3-AZ and 2-AZ layouts.
availability-zoneis free text: a config andINFOfield in 8.0, aHELLOfield in 8.1, and aCLUSTER SHARDSandCLUSTER SLOTSfield in 9.1. No GA release uses it for placement or failover.valkey-cli --cluster createspreads nodes by IP address only. Create one primary per zone with--cluster-replicas 0, then add each replica with--cluster-replica --cluster-primary-id.- A cluster survives a zone loss only if the other zones hold a majority of the slot-owning primaries and a replica of every lost primary. Keep fewer than half of the primaries in any one zone.
- Sentinel ranks
replica-priorityabove replication offset. Cluster ranks offset first, and the 9.2 release candidate'scluster-replica-priorityonly breaks ties. - A failover leaves two primaries in one zone. Move one back with
CLUSTER FAILOVERwhen the lost zone returns.
Scope and review date: November 2026. This post covers self-managed Valkey Cluster and Sentinel on 8.0 to 9.1 (latest patches 9.1.3 and 9.0.7), with the 9.2 release candidate (9.2.0-rc2, 4 November 2026) marked where it differs. Managed services that set zones for you are out of scope. Commands and behaviour were checked on 10 November 2026 against the valkey.io documentation, the release notes and the 9.1.3 and 9.2.0-rc2 source. They were not run in a lab, so rehearse them on staging.
Which Valkey versions understand availability zones?
Zone support arrived in three pieces, and the cluster tutorial mentions none of them. PR #700, shipped in 8.0, added the availability-zone config (empty by default, changeable with CONFIG SET) and an availability_zone line in INFO server. Its description says using it "when performing failover" would be ideal in the future. 8.1 added the field to the HELLO reply when it is set. 9.1.0 gossips the zone between cluster nodes and adds it to every node in CLUSTER SHARDS and CLUSTER SLOTS (PR #3156), again only when set.
| Version | What it added | Where you see the zone |
|---|---|---|
| 8.0 | availability-zone config, default empty | INFO server |
| 8.1 | Zone in the HELLO reply when set | HELLO 3 |
| 9.1 | Zone gossiped and kept in nodes.conf | CLUSTER SHARDS, CLUSTER SLOTS |
| 9.2 release candidate | cluster-replica-priority tie-breaker | valkey.conf, election log |
| Sentinel, any version | Nothing: Sentinel never reads the zone | Not applicable |
# valkey.conf on every node in us-east-1a
availability-zone "us-east-1a"# Or at runtime, then persist it
valkey-cli -h 10.0.1.11 CONFIG SET availability-zone us-east-1a
valkey-cli -h 10.0.1.11 CONFIG REWRITE
valkey-cli -h 10.0.1.11 INFO server | grep availability_zoneInterpretation: availability_zone:us-east-1a means the node reports its zone, and nothing after the colon means it is unset. In the 9.1.3 source a node reads its own zone from the config at startup, so a CONFIG SET never written to valkey.conf is lost on restart.
In the 9.1.3 source the zone appears only in replies, gossip and nodes.conf. Replica placement, replica migration, failure detection and elections never read it. It is free text, so spell it the same way on servers and clients.
What has to survive a zone loss in Valkey Cluster?
The cluster specification states it: the cluster survives partitions "where the majority of the primary nodes are reachable and there is at least one reachable replica for every primary node that is no longer reachable". Only primaries that own at least one slot count. A replica needs votes from (cluster_size / 2) + 1 of them, and a node that can reach fewer marks the cluster failed. With cluster-require-full-coverage yes (the default), one shard without an owner stops the whole cluster.
valkey-cli -h 10.0.2.11 CLUSTER INFO | grep -E 'cluster_state|cluster_size'Interpretation: cluster_size is the number of slot-owning primaries. With cluster_size:3 a failover needs 2 votes, so no zone may hold more than one primary.
The general rule: the primaries in any one zone must be fewer than half of cluster_size.
| Slot-owning primaries | Votes needed | Most in one zone | Fits in three zones? |
|---|---|---|---|
| 3 | 2 | 1 | Yes: 1, 1, 1 |
| 4 | 3 | 1 | No: one zone must hold 2 |
| 5 | 3 | 2 | Yes: 2, 2, 1 |
| 6 | 4 | 2 | Yes: 2, 2, 2 |
Four shards in three zones is the trap: losing the zone with two primaries leaves two votes where three are needed.
Three shards in three zones, and zone A goes dark
Pn is the primary of shard n and Rn a replica of it; each zone holds one primary and two replicas
After step 3: zone B holds two of the three primaries. Until one moves back to zone A, losing zone B leaves one vote where two are needed.
Why does valkey-cli --cluster create ignore zones?
It only knows IP addresses. In the 9.1.3 valkey-cli.c, create groups nodes by IP, interleaves the groups, and takes the first N nodes as primaries. Its anti-affinity score only penalizes replicas sharing an IP with their primary or a sibling. When every node has its own IP, the order you type decides the layout.
# Listed zone by zone: the first three addresses become the primaries
valkey-cli --cluster create \
10.0.1.11:6379 10.0.1.12:6379 10.0.1.13:6379 \
10.0.2.11:6379 10.0.2.12:6379 10.0.2.13:6379 \
10.0.3.11:6379 10.0.3.12:6379 10.0.3.13:6379 \
--cluster-replicas 2Interpretation: by our reading of the source, this makes all three 10.0.1.x nodes primaries, and the score is already zero, so nothing gets moved. Listing zones in turn (a, b, c, a, b, c) spreads the primaries but can still put a replica in its primary's zone. Read every Adding replica line before you answer Can I set the above configuration?.
The predictable layout is primaries first, then each replica placed by hand:
# 1. One primary per zone, no replicas yet
valkey-cli --cluster create \
10.0.1.11:6379 10.0.2.11:6379 10.0.3.11:6379 \
--cluster-replicas 0# 2. Replicas of the zone A primary go to zones B and C
PA=$(valkey-cli -h 10.0.1.11 -p 6379 CLUSTER MYID)
valkey-cli --cluster add-node 10.0.2.12:6379 10.0.1.11:6379 \
--cluster-replica --cluster-primary-id "$PA"
valkey-cli --cluster add-node 10.0.3.12:6379 10.0.1.11:6379 \
--cluster-replica --cluster-primary-id "$PA"Interpretation: --cluster-primary-id works from 8.0, beside the older --cluster-master-id. Repeat for the zone B primary (replicas in C and A) and the zone C primary (replicas in A and B).
Replica migration is zone-blind too: with the defaults cluster-allow-replica-migration yes and cluster-migration-barrier 1, a spare replica can move to an orphaned primary in its own zone. Re-check placement after any node replacement, and see replacing a failed Valkey Cluster node for the safe order.
Placing primaries and replicas across three zones
Seven steps for a new 3-shard cluster with two replicas per shard; none of them is an outage
-
Set the zone in every node's valkey.conf
Use the spelling your clients will use, in the file rather than only in
CONFIG SET.cluster-enabled yes availability-zone "us-east-1a" -
Start the nodes and check each zone
An empty value after the colon means the line did not load.
valkey-cli -h 10.0.1.11 INFO server \ | grep availability_zone -
Create one primary per zone
Three addresses in three zones and no replicas, so the order cannot pair primaries.
valkey-cli --cluster create 10.0.1.11:6379 \ 10.0.2.11:6379 10.0.3.11:6379 \ --cluster-replicas 0 -
Add shard 1's replicas in zones B and C
Name the primary by node ID so valkey-cli cannot choose another.
PA=$(valkey-cli -h 10.0.1.11 CLUSTER MYID) valkey-cli --cluster add-node 10.0.2.12:6379 \ 10.0.1.11:6379 --cluster-replica \ --cluster-primary-id "$PA" -
Add the replicas of shards 2 and 3
Zone B's primary gets replicas in C and A, and zone C's in A and B.
-
Check that every shard spans three zones
On 9.1 and later each shard should print 3. On 8.x, use the per-node loop below.
valkey-cli -h 10.0.1.11 --json CLUSTER SHARDS \ | jq -r '.[] | [.nodes[] | ."availability-zone"] | unique | length' -
Rehearse a zone loss on staging
Block one zone's client and cluster bus ports, then watch the other two.
watch -n1 "valkey-cli -h 10.0.2.11 \ CLUSTER INFO | grep cluster_state"
Main risk: the layout holds only until the first failover moves a primary. Repeat step 6 after every failover, planned or not.
How should you lay out two zones instead of three?
With two zones, one of them is not survivable on its own. Three primaries means one zone holds two. Losing the other zone is routine, but losing the zone with two leaves one vote, so no replica can win an election and the survivors report cluster_state:fail.
The way out is manual. CLUSTER FAILOVER TAKEOVER promotes a replica "without any agreement with the rest of the cluster" and "violates the last-failover-wins principle". Run it only after confirming the other zone is down, not just cut off, or two primaries own the same slots and one side's writes are lost when the partition heals.
# Zone A (two primaries) is confirmed down. On each zone B replica of an A primary:
valkey-cli -h 10.0.2.12 CLUSTER FAILOVER TAKEOVER
valkey-cli -h 10.0.2.13 CLUSTER FAILOVER TAKEOVERInterpretation: each replica becomes a primary at once, with a config epoch it generates alone. cluster_state:ok returns once every slot has an owner.
The majority zone can also move under you. If one zone A primary fails alone, its zone B replica is promoted and zone B now holds two primaries. cluster-replica-no-failover yes on zone B replicas pins primaries to zone A; the 9.1.3 valkey.conf describes it for "multiple data center operations". The cost: an A primary whose A replica is also down gets no automatic failover.
Two zones and three zones, with three shards
Switch layouts to see which single-zone loss each survives without an operator
Two zones
| Item | Two zones (A and B) |
|---|---|
| Primaries per zone | A: 2, B: 1 |
| Votes needed for a failover | 2 of 3 |
| Zone A lost | 1 vote left: manual TAKEOVER in B |
| Zone B lost | 2 votes left: the zone A replica of P3 is promoted |
| Replicas per shard | At least one, in the other zone |
| Sentinel placement | The third Sentinel needs a third location |
| After any single failover | The majority zone may flip from A to B |
Three zones
| Item | Three zones (A, B and C) |
|---|---|
| Primaries per zone | A: 1, B: 1, C: 1 |
| Votes needed for a failover | 2 of 3 |
| Zone A lost | 2 votes left: a replica of P1 in B or C is promoted |
| Zone B lost | 2 votes left: a replica of P2 in C or A is promoted |
| Replicas per shard | Two, one in each other zone |
| Sentinel placement | One Sentinel per zone, quorum 2 |
| After any single failover | One zone holds two primaries until you move one back |
Rule of thumb: if you can run anything in a third zone, run a slot-owning primary there. Valkey Cluster has no arbiter role, because only primaries that own slots vote.
Which replica does Valkey Cluster promote, and what does 9.2 change?
In 9.1.3, each replica of a failed primary gains one rank for every sibling with a higher replication offset, and for every sibling with the same offset and a smaller node ID. Each rank delays its request for votes, so the freshest replica normally asks first. The zone is not an input: the new primary lands wherever the freshest copy was.
The 9.2.0-rc1 release notes add cluster-replica-priority (PR #2204), which names the problem: "failover doesn't account for the AZ". The fix is narrow. Offset still comes first, and priority only orders replicas with equal offsets, before the node ID. A lower value ranks better, the default is 0, and a non-default value is persisted in nodes.conf (#4454).
# 9.2 release candidate only
# valkey.conf on replicas in the zone you want promoted first
cluster-replica-priority 0
# valkey.conf on replicas in the other zones
cluster-replica-priority 10grep "Start of election delayed" /var/log/valkey/valkey.logInterpretation: on 9.1 the line reads Start of election delayed for N milliseconds (rank #R, primary rank #P, offset O). and the 9.2.0-rc2 source appends replica priority N. Rank #0 asks first, and a replica that is behind keeps a worse rank whatever its priority.
The PR does not say how often offsets tie; our reading is that ties are likely at low write rates and rare under a steady write load. A replica you never want promoted automatically, such as a far-region backup copy, takes cluster-replica-no-failover yes.
cluster-replica-priority exists only in 9.2.0-rc1 and rc2 as of November 2026. Its name, default and semantics can change before 9.2.0 GA, and 9.1 nodes ignore it.
How does Sentinel choose a replica across zones?
Sentinel uses the opposite order. The Sentinel documentation and compareReplicasForPromotion() in the 9.1.3 source sort by replica-priority first, then replication offset, then the smaller run ID. Replicas disconnected for more than down-after-milliseconds times 10, plus the time the primary has been down, are skipped, and priority 0 means never promote.
That gives real zone control at a price: a lower-priority replica wins even when a sibling in another zone has more of the stream, so steering by zone can lose more acknowledged writes. Sentinel ignores availability-zone, so priority is its only zone signal. Set it on every instance, primaries included, because a primary becomes a replica after a failover.
# valkey.conf on the replica in the application's zone (us-east-1b)
replica-priority 50
# valkey.conf on every other instance, primaries included (100 is the default)
replica-priority 100Sentinels follow the same majority rule as cluster primaries. Quorum only decides that the primary is down; the failover needs a majority of all Sentinels to elect a leader. The documentation recommends at least three Sentinels on machines that fail independently, such as "Virtual Machines executed on different availability zones".
# sentinel.conf, one Sentinel in each of three zones
sentinel monitor cache-main 10.0.1.21 6379 2valkey-cli -p 26379 SENTINEL CKQUORUM cache-main
valkey-cli -p 26379 SENTINEL REPLICAS cache-main | grep -A1 -E 'slave-priority|slave-repl-offset'Interpretation: a healthy group answers +OK 3 usable Sentinels. Quorum and failover authorization can be reached. SENTINEL REPLICAS still uses the field names slave-priority and slave-repl-offset; check the priority Sentinel sees for each zone's replica.
With two zones, the third Sentinel still needs a third location: two in zone A and one in zone B cannot elect a leader once zone A is gone. The documentation's examples run Sentinels on client boxes for this reason. On 9.0, check the ACL change in Sentinel on Valkey 9 before a zone rehearsal.
How do you check the zone layout with CLUSTER SHARDS?
On 9.1 and later, one command lists every node's role, health and zone. valkey-cli --json uses RESP3 by default, so each node arrives as a JSON object for jq. Nodes without a zone omit the field.
CLUSTER SHARDS with availability-zone on Valkey 9.1
Illustrative output: three shards, one primary and two replicas each, one node per zone
What to look for: one master per zone and three zones inside each shard. The field names follow the CLUSTER SHARDS reference, which lists the node-level availability-zone under 9.1.0; the IDs and addresses are invented.
For alerting, count online primaries per zone:
valkey-cli -h 10.0.1.11 --json CLUSTER SHARDS | jq -r '
[.[] | .nodes[] | select(.role == "master" and .health == "online")
| (."availability-zone" // "unset")]
| group_by(.) | map("\(.[0])\t\(length)") | .[]'Interpretation: a zone whose count reaches half of cluster_size is a zone you cannot lose. An unset row is a primary without a zone.
On 8.0 and 8.1 the zone is not gossiped, so ask each node:
valkey-cli -h 10.0.1.11 CLUSTER NODES \
| awk '{split($2, a, "@"); print a[1], ($3 ~ /master/ ? "primary" : "replica")}' \
| while read -r addr role; do
az=$(valkey-cli -h "${addr%:*}" -p "${addr##*:}" CONFIG GET availability-zone | tail -1)
echo "$addr $role ${az:-unset}"
doneInterpretation: one line per node, such as 10.0.2.11:6379 primary us-east-1b. Add your authentication and TLS options to both calls. Client libraries parse CLUSTER SHARDS too, and one Go client broke on its 9.1 changes (see Valkey client breaking changes).
What should you do after the lost zone comes back?
Move a primary back. The cluster specification says a failed primary that rejoins will "reconfigure to replicate from the new primary", so the layout does not repair itself.
# On the old P1, now a replica in zone A
valkey-cli -h 10.0.1.11 INFO replication | grep master_link_status
valkey-cli -h 10.0.1.11 CLUSTER FAILOVERInterpretation: wait for master_link_status:up. A plain CLUSTER FAILOVER pauses writes on the primary and promotes the replica once it has the whole stream. The pause is bounded by cluster-manual-failover-timeout, 5000 ms by default and configurable since 8.1.
Then count primaries per zone again. Rehearse the sequence on staging by blocking the zone's ports, not by stopping one process, because the cluster bus decides the vote.
How do zone-aware clients use the availability-zone field?
The zone was added for clients, and reads are where it pays off. Valkey GLIDE's AZ affinity offers AZ_AFFINITY, which prefers replicas in the client's zone, and AZ_AFFINITY_REPLICAS_AND_PRIMARY, which tries a same-zone primary before other zones. Some managed services set the server zone for you; on self-managed nodes it comes from your valkey.conf.
from glide import GlideClusterClient, GlideClusterClientConfiguration, NodeAddress, ReadFrom
# Inside an async function
config = GlideClusterClientConfiguration(
[NodeAddress(host="10.0.1.11", port=6379)],
read_from=ReadFrom.AZ_AFFINITY,
client_az="us-east-1a",
)
client = await GlideClusterClient.create(config)Interpretation: reads go to a us-east-1a replica when one is available, and can be slightly stale because replication is asynchronous. Writes still go to the slot's primary in whatever zone it is.
Replication also crosses zones on every write. The replication topic documents repl-compression for links "such as between availability zones". It is a 9.2 release candidate setting (LZ4 in rc1, Zstandard added in rc2) and must be set on both primary and replica.
Production checklist for 3-AZ and 2-AZ placement
Three zones
- Fewer than half of the slot-owning primaries in any zone: 1, 1, 1 for three shards. Avoid four shards.
- Two replicas per shard, one in each other zone, added with
--cluster-primary-id. - One Sentinel per zone with quorum 2, if you run Sentinel.
Two zones
- An odd number of primaries, the majority in the zone you protect, and a written
TAKEOVERrunbook for losing that zone. - Optionally
cluster-replica-no-failover yeson minority-zone replicas, and a third Sentinel in a third location.
Both
availability-zonein everyvalkey.conf, checked withINFO server.- Primaries per zone checked after every failover, with an alert at half of
cluster_size. - A staging game day that blocks a zone's ports, then moves the primary back with
CLUSTER FAILOVER.
Frequently asked questions
Does Valkey use the availability-zone setting during failover?
No. In every GA release up to 9.1.3, the zone is reported in INFO, HELLO and, from 9.1, CLUSTER SHARDS and CLUSTER SLOTS, but elections and replica placement ignore it. The 9.2 release candidate adds cluster-replica-priority, which you can set per zone, but it only breaks ties between replicas with equal replication offsets.
How many availability zones does a Valkey cluster need?
Three, if every single-zone loss should fail over without an operator. A failover needs votes from a majority of slot-owning primaries, so no zone may hold half of them or more. With two zones, one zone always holds the majority, and losing it needs a manual CLUSTER FAILOVER TAKEOVER in the surviving zone.
What is the difference between replica-priority and cluster-replica-priority?
replica-priority is read by Sentinel and outranks replication offset, so a preferred replica wins even when it is behind. cluster-replica-priority is a Valkey Cluster setting in the 9.2 release candidate that only orders replicas with the same offset. In both, a lower value is preferred, and replica-priority 0 means Sentinel never promotes that replica.
Where should Sentinels run in a two-zone Valkey deployment?
Put the third Sentinel outside both data zones, such as on an application host or a small instance in a third zone. A failover needs a majority of all Sentinels to elect a leader, so two Sentinels in one zone and one in the other cannot fail over when the zone with two is lost.
Plan a multi-AZ Valkey layout with JusDB
JusDB's Valkey high availability team can review your zone layout, replica priorities and Sentinel placement against the failure cases in this post, and plan a zone game day that fits your hosting.
Bring your Valkey versions, your CLUSTER SHARDS or SENTINEL REPLICAS output, and how nodes are assigned to zones today. Your team approves every production change.