Redis READONLY You can’t write against a read only replica - causes and fixes

Your application hits (error) READONLY You can't write against a read only replica. Writes fail; reads work. The connected Redis instance thinks it is a replica, so it rejects mutating commands. The replica is behaving correctly. The problem is a write-capable client routed to a node that is not the current primary. This typically happens in three situations: a routing bug that sends writes to a replica endpoint, stale client topology after a failover or upgrade, or an instance that was accidentally demoted at runtime.

What this means

Replicas operate in read-only mode by default via the replica-read-only yes directive (called slave-read-only before Redis 5). When a client issues a write command such as SET, DEL, or LPUSH to a replica, Redis returns the READONLY error to prevent dataset divergence from the primary. The mode can be toggled at runtime with CONFIG SET replica-read-only yes|no, and it is automatically enforced when an instance becomes a replica via REPLICAOF host port. The error signals a topology mismatch: the client expects a master, but the server reports role:slave.

Common causes

CauseWhat it looks likeFirst thing to check
Routing bug or hardcoded replica endpointWrites fail consistently from specific clients; reads against the same node succeedINFO replication role and slave_read_only on the target node
Stale topology after failover, upgrade, or restartErrors spike immediately after a failover event; some application instances work while others do notClient connection target and Sentinel or load balancer state
Runtime reconfiguration (REPLICAOF, accidental demotion)All writes to the node fail after maintenance or an operator command; the node should be a masterINFO replication role and CONFIG GET replica-read-only
Client read preference routing write commands to replicasIntermittent READONLY during normal operations; often affects Lua scripts or transactions routed to replicasClient library read-routing configuration

Quick checks

# Confirm instance role and read-only state
redis-cli INFO replication | grep -E "role|slave_read_only"

# Check runtime read-only configuration
redis-cli CONFIG GET replica-read-only

# Check if error replies are climbing
redis-cli INFO stats | grep total_error_replies

# Check replication link and offset lag on a replica
redis-cli INFO replication | grep -E "master_link_status|master_repl_offset|slave_repl_offset"

# Examine connected clients and their origin
redis-cli CLIENT LIST | head -20

# If using Sentinel, verify which node is currently master
redis-cli -p 26379 SENTINEL MASTER mymaster

How to diagnose it

flowchart TD
  A[Client issues write] --> B{INFO replication role}
  B -->|master| C[Write accepted]
  B -->|slave| D[READONLY error]
  D --> E{Should this node be master?}
  E -->|Yes| F[Check: failover, Sentinel, CONFIG drift]
  E -->|No| G[Fix: route writes to actual master]
  F --> H[Verify master_repl_offset across nodes]
  F --> I[Check client topology refresh]
  F --> J[Audit CONFIG SET / REPLICAOF history]
  1. Confirm the node’s role. Run INFO replication on the instance returning the error. If role:slave and slave_read_only:1, the node is correctly behaving as a read-only replica.
  2. Verify whether this node should be a master. Compare against your deployment topology. If it should be a master, it has been demoted.
  3. Check for recent failover or restart events. Look at uptime_in_seconds for unexpected resets, review Sentinel logs, or check your cloud provider’s maintenance event history.
  4. Inspect client routing configuration. Check application connection strings, DNS records, and load balancer targets for hardcoded replica IPs or stale primary endpoints.
  5. Look for runtime reconfiguration. Run INFO commandstats and scan for cmdstat_replicaof or cmdstat_config increases. Check Redis server logs for recent CONFIG SET commands.
  6. Audit client library topology state. For Lettuce, Spring Data Redis, go-redis, or ioredis, check whether connections were established before failover completed and whether topology refresh is enabled. Verify that write commands are not being sent with replica-preferring read settings.
  7. Measure replication offset lag. If you have multiple candidates for primary, compare master_repl_offset across nodes to identify which one is actually leading.

Metrics and signals to monitor

SignalWhy it mattersWarning sign
role in INFO replicationDetects unexpected demotion from master to replicarole:slave on a node expected to be master
slave_read_onlyConfirms read-only mode is activeValue of 1 on a node receiving write attempts
total_error_replies rateCaptures write rejections and other errorsSustained increase after topology changes
master_repl_offset vs slave_repl_offsetQuantifies replication lag and identifies the true primaryOffset not increasing on the node clients treat as master
sync_full and sync_partial_errIndicates replicas are falling behind and requiring full resyncsSpikes after failovers or network blips
cmdstat_replicaof / cmdstat_configDetects runtime topology changes via commandsNon-zero counts outside maintenance windows

Fixes

Route writes to the current primary

If the node is legitimately a replica, redirect write-capable clients to the current primary. Update connection strings, service discovery records, or load balancer targets. Do not hardcode individual node endpoints in HA deployments. On AWS ElastiCache, use the primary endpoint rather than node endpoints.

Refresh stale client topology

When client libraries cache topology across failover:

  • Restart application instances that hold stale connections to the old primary.
  • Reduce topology refresh intervals in client configuration during planned maintenance.
  • For Lettuce-based clients, validate that writes use master routing and that replica preferences are reserved for confirmed read-only operations.

Promote the replica back to primary

If the node was incorrectly demoted:

  • Run REPLICAOF NO ONE to make it an independent master. Warning: Only do this if you are certain no other master is active for the same dataset. Creating a split-brain will diverge data.
  • If Sentinel manages the topology, prefer Sentinel-driven failover instead of manual promotion.

Temporarily allow writes on the replica

In emergencies, run CONFIG SET replica-read-only no. Warning: This causes the replica to accept writes and diverge from its primary. Use only as a temporary measure, and rebuild the replica afterwards.

Rebuild the replica

If the replica diverged or you enabled temporary writes:

  1. Run REPLICAOF NO ONE to clear the existing replication link if necessary.
  2. Run REPLICAOF correct_primary_host port to reattach.
  3. Allow a full resync to complete. Monitor master_link_status and offset lag until the replica is caught up.

Prevention

  • Use primary and reader endpoints rather than individual node IPs. In Kubernetes, ensure the service or operator endpoint targets the current master.
  • Configure client libraries with topology refresh so they detect failovers faster than application-level connection timeouts.
  • Monitor role and slave_read_only on every node that should accept writes.
  • Restrict CONFIG and REPLICAOF commands using ACLs or rename-command to prevent accidental or unauthorized demotion.
  • Set min-replicas-to-write and min-replicas-max-lag to prevent the primary from accepting writes when replicas are disconnected or severely lagging.

How Netdata helps

  • Charts INFO replication role transitions alongside total_error_replies spikes, so you can pinpoint when a demotion causes write failures.
  • Tracks replication offset lag and master_link_status per node to verify a promoted replica is healthy before routing writes.
  • Surfaces uptime_in_seconds resets next to connection spikes to distinguish cold-start topology issues from persistent routing bugs.
  • Highlights commandstats for replicaof and config executions that precede unexpected READONLY errors.
  • Monitors connected_clients on former primaries after failover to detect applications still sending traffic to the old node.