Skip to main content
Redis · lesson 8 of 14
Redis intermediate Lesson 8 of 14

Replication: A Read-Only Replica, and What WAIT Actually Guarantees

Writing directly to a replica fails with READONLY by design — and WAIT doesn't error when it can't reach the number of replicas you asked for, it just tells you how many actually acknowledged in time.

By SkillByExample · Published

redis replication wait high-availability

Two containers, one replicating from the other — and a couple of guarantees that turn out to be narrower than they sound.

Setting up a replica

docker network create redis-net
docker run -d --name redis-lesson --network redis-net -p 6379:6379 redis:8-alpine
docker run -d --name redis-replica --network redis-net -p 6380:6379 redis:8-alpine
docker exec redis-replica redis-cli REPLICAOF redis-lesson 6379
OK
docker exec redis-lesson redis-cli INFO replication | head -3
# Replication
role:master
connected_slaves:1

The master sees one connected replica. Writing to the master and reading from the replica confirms the link actually works:

docker exec redis-lesson redis-cli SET synced "from the master"
docker exec redis-replica redis-cli GET synced
OK
from the master

The bug: writing directly to the replica

docker exec redis-replica redis-cli SET direct "trying to write to replica"
READONLY You can't write against a read only replica.

replica-read-only is on by default precisely to prevent this — a replica is meant to be an exact copy, and accepting its own independent writes would let it drift from the master instead of mirroring it.

WAIT: not an error, just an honest count

docker exec redis-lesson redis-cli SET important "must be replicated"
docker exec redis-lesson redis-cli WAIT 1 1000
OK
1

WAIT 1 1000 asked for at least 1 replica to acknowledge, within 1000ms — got it immediately, since the one replica was already caught up. Now ask for more replicas than actually exist:

docker exec redis-lesson redis-cli SET another "value"
time docker exec redis-lesson redis-cli WAIT 2 1000
OK
1

real	0m1.618s

WAIT 2 1000 can never reach 2 acknowledgments with only one replica connected — it waits out the full ~1 second timeout (the real 0m1.618s confirms it actually blocked, not returned instantly) and then reports 1, the real number that acknowledged. WAIT never raises an error for “not enough replicas”; it always returns the true count it observed at the deadline, and it’s the caller’s job to decide whether that count was good enough.

Promoting a replica

docker exec redis-replica redis-cli ROLE
slave
redis-lesson
6379
connected
281
docker exec redis-replica redis-cli REPLICAOF NO ONE
docker exec redis-replica redis-cli ROLE
OK
master
281

REPLICAOF NO ONE detaches the replica and makes it an independent master immediately, keeping every write it had already replicated (offset 281, unchanged) — this is the command a failover process runs once it’s decided the original master is gone for good.

Practice

1. Check a server's replication role without reading the full INFO output.
docker exec redis-lesson redis-cli ROLE
master
281

ROLE is the compact, script-friendly version of what INFO replication reports in prose — for a master it’s role, offset, and a list of connected replicas (empty here, since the former replica already promoted itself away).

2. Confirm the promoted former-replica now accepts writes of its own.
docker exec redis-replica redis-cli SET independent "no longer read-only"
docker exec redis-replica redis-cli GET independent
OK
no longer read-only

No READONLY error this time — once promoted via REPLICAOF NO ONE, it behaves exactly like any other standalone master.

3. Check replication info from the (now-independent) former replica's own perspective.
docker exec redis-replica redis-cli INFO replication | head -3
# Replication
role:master
connected_slaves:0

role:master and connected_slaves:0 confirm it: fully independent now, no longer reporting to or replicating from redis-lesson at all.

Next: ACL and security — users, selectors, and key-level read/write permissions.

Frequently Asked Questions

Is Redis replication synchronous or asynchronous?
Asynchronous by default — a write on the master returns to the client immediately, and the replica catches up shortly after over its own connection. This is fast but means a master crash between the write and replication can lose that write; WAIT exists specifically to get a stronger (though still not absolute) guarantee when a particular write needs it.
Why did writing directly to the replica fail?
replica-read-only is on by default specifically to prevent exactly that mistake — a replica is supposed to be an exact copy of the master, and accepting independent writes would let it drift. It can be turned off, but Redis's own docs call writable replicas a legacy feature kept for backward compatibility, not a recommended pattern, since inconsistency between master and replica is easy to introduce that way.
What does WAIT 2 1000 actually mean, and what happens if only 1 replica exists?
It asks the server to block until at least 2 replicas have acknowledged the current replication offset, or 1000ms passes, whichever comes first. With only one replica connected, it can never reach 2 — so it waits out the full timeout and then returns however many actually acknowledged (1), not an error. WAIT never fails outright; it always reports the real count it observed.
Does WAIT make a write fully durable?
No — it reduces the window for losing an acknowledged write, but Redis's own documentation is explicit that WAIT does not turn a set of instances into a strongly consistent system. An acknowledged write can still be lost during a failover depending on the exact persistence configuration on the instances involved; WAIT is risk reduction, not a durability guarantee.
How do I turn a replica back into an independent master?
REPLICAOF NO ONE — it stops replicating from its former master and starts accepting writes of its own immediately, keeping whatever data it had already replicated. This is the command a failover process runs to promote a replica when the original master is gone.