Incident Response

Redis "READONLY You can't write against a read only replica": Causes and Fixes

The error almost never means Redis is broken. It means your application is writing to a node that is no longer, or never was, the primary. Here is how to find out why and fix it without risking your data.

· 12 min read · AG Data Team

READONLY You can't write against a read only replica is the reply Redis gives when a write command reaches a replica. By default replicas accept reads only, so the server refuses the write. In almost every incident the database is fine. The problem is that the application is connected to the wrong node, usually right after a failover.

The Redis error reference puts it simply: only the primary accepts writes. Valkey, which forked from Redis, behaves the same way and uses the same message. So the question is not "what is wrong with Redis", but "why does my client think this replica is the primary?"

First, check what the node really is

$ redis-cli -h cache-01 SET k v
(error) READONLY You can't write against a read only replica.

$ redis-cli -h cache-01 ROLE
1) "slave"
2) "10.0.2.15"          # the primary this node follows
3) (integer) 6379
4) "connected"
5) (integer) 3167038

$ redis-cli -h cache-01 INFO replication | head -5
# Replication
role:slave
master_host:10.0.2.15
master_port:6379
master_link_status:up

ROLE returns slave as the first element on a replica (the word stays in the protocol for backward compatibility), followed by the primary's address, the link state and the replication offset. INFO replication gives the same picture in text form. If the node is a replica, look at which primary it follows. That tells you where the writes should have gone.

The usual causes

Scripts and "read" commands that are really writes

The error reference notes that a Lua function, or a script starting with a #!lua line, gets READONLY on a replica before it starts unless it has the no-writes flag. A plain script gets the error when it calls a write command. The replication documentation also points out that EVAL, EVALSHA and SORT are not read-only commands. If you want to run them on replicas, use EVAL_RO, EVALSHA_RO and SORT_RO, and replace SUNIONSTORE or ZINTERSTORE into temporary keys with SUNION or ZINTER.

Fix the client, not the replica

  1. With Sentinel, let the client discover the primary. The Sentinel client specification describes the procedure: ask a Sentinel with SENTINEL get-master-addr-by-name, connect, and confirm with ROLE that the node really is a master. On every reconnection the client should ask Sentinel again. When Sentinel reconfigures an instance it sends CLIENT KILL type normal, which forces clients to reconnect and resolve the address again. A client that reconnects to a cached address defeats this.
  2. On ElastiCache, write only to the primary endpoint (or the configuration endpoint in cluster mode), and make sure the runtime does not cache DNS for longer than the failover window.
  3. Treat READONLY as a reconnect signal. Many clients can be configured to drop the connection and rediscover the primary when they see it. Retrying the same write on the same connection will fail every time.
  4. Separate write and read endpoints. In Kubernetes, give writes a Service that only selects the current primary. Sentinel-aware clients or an operator that labels the primary handle this. A Service over all pods does not.
# ask Sentinel who the primary is right now
$ redis-cli -p 26379 SENTINEL get-master-addr-by-name mymaster
1) "10.0.2.21"
2) "6379"

# then verify on that node before trusting it
$ redis-cli -h 10.0.2.21 ROLE
1) "master"
...
Do not set replica-read-only no to make the error go away. The Redis documentation says writable replicas exist only for historical reasons and can make the replica's data differ from the primary's. Writes on a replica are discarded on resync or restart, they are not propagated to sub-replicas, and if that node is ever promoted you start from an inconsistent dataset.

Related errors that look similar

What changes with large datasets

With tens of gigabytes in memory, the minutes after a failover are where READONLY turns into a longer outage:

The same rules apply if you have moved or plan to move to Valkey, see our Redis to Valkey migration guide: replicas are read-only by default and clients must follow the primary.

Key takeaways

Redis Valkey Replication Sentinel
Work with us

Writes failing with READONLY?

We troubleshoot Redis and Valkey failovers, fix client discovery for Sentinel, Cluster and ElastiCache, and make failover predictable for large datasets.

Get in touch More from the blog