Rebalancing Cluster Slots After Adding a Node
You have just brought a new primary into a running Redis Cluster with CLUSTER MEET, and it has joined the gossip mesh — but it owns zero of the 16,384 hash slots, so it holds no data and serves no traffic. The three original primaries are still each responsible for roughly a third of the keyspace, and the memory pressure that motivated the expansion has not moved. This page shows how to redistribute slots onto that empty node evenly while the Redis cluster keeps serving reads and writes, using the tooling that ships with redis-cli. The migration itself is an online operation built on the same slot-handoff protocol described in zero-downtime slot migration; here the focus is the specific case of filling a brand-new, empty primary and controlling exactly how much of the keyspace lands on it.
Prerequisites
- A running Redis 7.x cluster with at least three primaries, reachable via
redis-cli. - The new primary already joined through
CLUSTER MEETand visible to every node — confirmed below. redis-clifrom the same 7.x line so the--clustersubcommands match the server protocol.- Cluster-bus connectivity (the data port plus
port + 10000) open between all nodes, including the new one. redis-py5.x on Python 3.10+ (pip install "redis>=5,<6") for the client-sideMOVEDmonitoring in the last step.- A brief window of slightly elevated latency tolerance: migrating keys competes with live traffic for CPU.
Step-by-Step Rebalance
1. Verify the new node actually joined
Before moving a single slot, confirm the new primary is a known, connected member and not a handshake-stuck or fail?-flagged ghost. CLUSTER NODES prints one line per node; the new one should be master with an empty slot range at the end of its line.
# The new node must show role "master", state "connected", and no slot range.
redis-cli -h 10.0.0.14 -p 6379 CLUSTER NODES | grep myself
# e.g. <id> 10.0.0.14:6379@16379 myself,master - 0 0 0 connected
2. Rebalance to fill the empty primary
redis-cli --cluster rebalance computes an even target distribution and moves the minimum number of slots to reach it. By default it ignores primaries that currently hold zero slots, so a new empty node stays empty — you must pass --cluster-use-empty-masters to make it a valid destination.
# Point at ANY node in the cluster; --cluster-use-empty-masters makes the
# freshly added primary eligible to receive slots.
redis-cli --cluster rebalance 10.0.0.11:6379 --cluster-use-empty-masters
3. Control the target distribution with weights
An even split is not always what you want — a node on larger hardware should carry more slots. --cluster-weight assigns a relative weight per primary (by node ID); the rebalancer sizes each node's slot count in proportion. A weight of 0 drains a node instead of filling it.
# The new node (id ...e14) gets double the share of the three originals.
redis-cli --cluster rebalance 10.0.0.11:6379 --cluster-use-empty-masters \
--cluster-weight <id-a>=1 <id-b>=1 <id-c>=1 <id-e14>=2
4. Or move an exact slice with a targeted reshard
When you want deterministic control instead of an automatic plan — for example moving exactly one quarter of the keyspace from one hot primary — use --cluster reshard with explicit source, destination, and slot count. This is the surgical alternative to the automatic rebalance and mirrors the manual flow in the step-by-step migration guide.
# Move 4096 slots FROM the most-loaded primary TO the new node, no prompts.
redis-cli --cluster reshard 10.0.0.11:6379 \
--cluster-from <id-of-hot-primary> \
--cluster-to <id-e14> \
--cluster-slots 4096 \
--cluster-yes
5. Throttle the migration with pipelining
Each slot is migrated key by key with MIGRATE. --cluster-pipeline sets how many keys are moved per MIGRATE round trip (default 10); lowering it reduces the CPU each batch steals from live traffic, while raising it finishes faster on an idle cluster. Tune it to protect your latency SLO during business hours.
# Gentler on a busy cluster: fewer keys per MIGRATE batch = smaller latency blips.
redis-cli --cluster reshard 10.0.0.11:6379 \
--cluster-from <id-of-hot-primary> --cluster-to <id-e14> \
--cluster-slots 4096 --cluster-pipeline 5 --cluster-yes
6. Give the new primary a replica
A primary with no replica is a single point of failure: if it dies mid-life, the slots it now owns are lost until a manual repair. Attach a replica so the newly balanced shard is as available as the originals — the provisioning side of this is automated in automated node provisioning.
# Run ON the replica node: join, then replicate the new primary by its id.
redis-cli -h 10.0.0.15 -p 6379 CLUSTER MEET 10.0.0.11 6379
redis-cli -h 10.0.0.15 -p 6379 CLUSTER REPLICATE <id-e14>
7. Watch clients absorb MOVED during the move
While slots are in flight, clients that cached the old slot map briefly receive MOVED (slot settled on the new owner) or ASK (key mid-migration) redirections. A well-configured redis-py cluster client refreshes its slot map on MOVED transparently; monitor that it is happening rather than erroring.
import asyncio
from redis.asyncio.cluster import RedisCluster
async def watch_redirects() -> None:
# require_full_coverage=False tolerates the brief window where a slot
# is mid-handoff; the client re-reads CLUSTER SLOTS on each MOVED.
rc = RedisCluster(host="10.0.0.11", port=6379, decode_responses=True,
require_full_coverage=False)
for i in range(10_000):
# A hash tag pins related keys to one slot so they migrate together.
await rc.set(f"user:{{{i}}}:seen", "1", ex=300)
await rc.aclose()
asyncio.run(watch_redirects())
Failure Modes
New node stays empty after rebalance. You ran redis-cli --cluster rebalance and nothing moved — the tool reported "Nothing to move." This is the single most common surprise: without --cluster-use-empty-masters the rebalancer treats a zero-slot primary as intentionally drained and excludes it. Diagnose by confirming the node still owns no slots and then re-run with the flag:
redis-cli --cluster check 10.0.0.11:6379 | grep -A1 10.0.0.14
# 0 slots reported => rerun rebalance WITH --cluster-use-empty-masters
Rebalance aborts on an open slot. If a previous migration was interrupted, a slot can be left in importing/migrating state, and the rebalancer refuses to plan around it. Diagnose with --cluster check, which prints [WARNING] ... has slots in importing/migrating state, then fix the stuck slot before retrying:
redis-cli --cluster check 10.0.0.11:6379 # look for open slots
redis-cli --cluster fix 10.0.0.11:6379 # settle any half-migrated slot
Latency spikes during migration. Live traffic slows because each MIGRATE batch and the target node's key deserialization compete with command processing. Diagnose by watching the slow log and per-command latency on the busiest node while slots move, then lower --cluster-pipeline (or run off-peak):
redis-cli -h 10.0.0.11 -p 6379 --latency-history # watch the moving average
redis-cli -h 10.0.0.11 -p 6379 SLOWLOG GET 10 # MIGRATE showing up here?
Verification
Confirm the keyspace is now spread across every primary, including the new one, and that no slot is uncovered or open:
redis-cli --cluster check 10.0.0.11:6379
# expect: "[OK] All 16384 slots covered." and roughly even slot counts
Read the new node's own slot ownership directly — it should now report a healthy, non-empty range and a live keyspace:
redis-cli -h 10.0.0.14 -p 6379 CLUSTER NODES | grep myself # slot range present
redis-cli -h 10.0.0.14 -p 6379 DBSIZE # keys now resident
Verify the new primary has a connected replica so the shard is not a single point of failure:
redis-cli -h 10.0.0.14 -p 6379 INFO replication | grep -E "role|connected_slaves"
# expect role:master and connected_slaves:1
FAQ
What is the difference between rebalance and reshard?
redis-cli --cluster rebalance computes an even (or weight-proportional) target distribution across all primaries and moves the minimum number of slots to reach it — you declare the goal, it plans the moves. redis-cli --cluster reshard moves an exact number of slots from specific source nodes to a specific destination that you name explicitly. Use rebalance to level the whole cluster after adding a node; use reshard when you want deterministic, surgical control over which slots go where.
Do I really need --cluster-use-empty-masters?
Yes, whenever the destination is a primary that currently owns zero slots — which a freshly added node always does. The rebalancer deliberately skips empty primaries by default, on the assumption that a zero-slot node is being drained or decommissioned. Without the flag it will report "Nothing to move" and leave your new node idle. The flag tells it to treat empty primaries as valid fill targets.
Is rebalancing an online operation?
Yes. Slots move one key at a time using the Redis cluster's MIGRATE-based handoff, and the Redis cluster continues serving reads and writes throughout. Clients see brief MOVED and ASK redirections for the slots in flight, which any current cluster-aware client absorbs by refreshing its slot map. The only cost is some extra CPU and a modest latency increase during the move, which you throttle with --cluster-pipeline.
How do I keep a hot slot's keys together during the move?
Use a hash tag so related keys hash to the same slot and therefore migrate as a unit. Wrapping part of the key in braces, as in user:{1234}:profile and user:{1234}:sessions, makes Redis hash only the 1234 inside the braces, co-locating both keys. This is the same slot-pinning technique covered in slot allocation basics; it does not spread a genuinely hot single slot, but it stops a multi-key operation from splitting across shards mid-migration.
How long does a rebalance take?
It scales with the number of keys moved, their sizes, and network throughput between nodes — not with the raw slot count. Moving 4096 mostly-small slots on a healthy LAN typically completes in minutes; large values, cross-datacenter links, or a low --cluster-pipeline extend it. Watch progress live with redis-cli --cluster check, which reports the remaining per-node slot counts as they converge on the target.
Up: Zero-Downtime Slot Migration