understanding PSYNC, backlog sizing, and resync mechanics
Redis replication looks simple at first glance: one command, one connection, data flows from master to replica. Underneath, though, the PSYNC protocol decides whether a brief network interruption costs only a few kilobytes or requires retransferring the entire dataset, and an incorrectly sized backlog regularly wipes out exactly that advantage in practice.
Table of Contents
- 1. Basic principle of Redis replication
- 2. The PSYNC protocol in detail
- 3. Partial resync vs. full resync
- 4. Replication backlog: sizing it correctly
- 5. replica-read-only and write protection on replicas
- 6. Detecting and minimizing replication lag
- 7. Diskless replication and RDB transfer
- 8. Chained replication: sub-replicas
- 9. Monitoring replication with INFO replication
- 10. Summary
- 11. FAQ
1. Basic principle of Redis replication
Redis replication follows an asynchronous master replica model: the master processes write commands, appends them to an internal replication stream, and continuously sends that stream to every connected replica. The replicas apply the same commands in the same order to their own copy of the data. Asynchronous here means the master does not wait for a replica's acknowledgement before telling the client that a write command succeeded, which preserves Redis's low latency but also means replicas can always lag slightly behind the master.
Every replica connects to the master over a dedicated TCP connection and identifies itself with a replication ID and an offset that indicates the position in the replication stream it has already synchronized up to. These two values are the key to everything described in the following sections, since they determine whether a replica can catch up on just the missing commands after an interruption or has to resynchronize from scratch.
It is important to understand that Redis replication by design offers no consistency guarantee in the sense of synchronous replication. Redis can optionally wait for a minimum number of acknowledging replicas via WAIT, but that is an explicit application decision, not the default behavior. Anyone unaware of this property and blindly relying on immediate consistency between master and replicas is building assumptions into their application that no longer hold under load or during network issues.
2. The PSYNC protocol in detail
The PSYNC command, the standard replication mechanism since Redis 2.8, replaced the older SYNC command to enable intelligent resumption after connection drops. On the very first connection, the replica sends PSYNC ? -1, signaling that it has no known replication ID and no offset, and thereby implicitly requests a full synchronization. The master responds with +FULLRESYNC <replid> <offset> and begins transferring an RDB snapshot followed by the live command stream.
After a successful initial synchronization, the replica knows both the master's replication ID and its own current offset. If the connection later drops, for example due to a brief network issue, the replica sends PSYNC <replid> <offset> with these stored values on reconnect. The master checks whether it recognizes that replication ID and whether the requested offset is still present in its replication backlog. If both are true, it responds with +CONTINUE and sends only the commands missing since the last known offset, instead of retransferring the entire dataset.
# Observe the PSYNC handshake at the protocol level (simplified)
# Initial sync from a brand-new replica:
# Replica -> Master: PSYNC ? -1
# Master -> Replica: +FULLRESYNC 8f3e9a2b1c4d5e6f 88213
# Master -> Replica: <RDB snapshot bytes>
# Master -> Replica: <live command stream from offset 88213>
# Reconnect after a brief network blip:
# Replica -> Master: PSYNC 8f3e9a2b1c4d5e6f 91045
# Master -> Replica: +CONTINUE 8f3e9a2b1c4d5e6f
# Master -> Replica: <only commands from offset 91045 onward>
# Inspect the replication ID and offset directly
redis-cli -p 6379 info replication | grep -E "master_replid|master_repl_offset"
This mechanism is why brief network interruptions remain practically invisible in a well configured Redis replication setup: instead of retransferring gigabytes of data, master and replica exchange only the few commands that occurred during the interruption. How large this window for a successful partial resync actually is depends directly on the size of the replication backlog, the topic of the section after next.
3. Partial resync vs. full resync
The difference between partial resync and full resync has a massive impact on network load, CPU load, and the time it takes for a replica to become fully synchronized again. A full resync forces a complete new RDB snapshot to be built on the master, transferred over the network, and loaded on the replica, which for large datasets can take minutes and generate significant CPU and I/O load on both sides in the meantime. A partial resync, by contrast, only involves the commands actually missing since the last known position, typically a few kilobytes to megabytes.
A full resync is always forced when the replica reports an unknown replication ID, for example after a master restart with a changed ID, or when the requested offset is no longer present in the replication backlog because too much time has passed since the last contact. A full resync is also unavoidable on a brand new replica's very first connection, since there simply is no basis for a partial resync yet.
# Count full vs. partial resyncs since the master started
redis-cli -p 6379 info stats | grep -E "sync_full|sync_partial_ok|sync_partial_err"
# sync_full:3 # forced complete resyncs (expensive)
# sync_partial_ok:47 # cheap partial resyncs (the goal)
# sync_partial_err:2 # partial attempted but failed, fell back to full
# A high sync_partial_err count relative to sync_partial_ok
# usually means the backlog is too small for typical outage windows
A high ratio of sync_partial_err relative to sync_partial_ok is a reliable warning sign: it shows that replicas are regularly attempting to reconnect via partial resync but failing, usually because the backlog is not large enough to cover the typical duration of network interruptions. This ratio should be a fixed part of every Redis monitoring setup, since it directly shows whether the current backlog configuration matches actual network stability.
4. Replication backlog: sizing it correctly
The replication backlog is a ring buffer in the master's memory that retains the most recently written commands of the replication stream for a limited time. Its size, configured via repl-backlog-size, directly determines how long a replica can stay offline before a partial resync is no longer possible and an expensive full resync gets forced instead. The default value of 1 MB is considerably too small for many production setups.
Correctly sizing the backlog follows a simple formula: backlog size = estimated maximum outage duration in seconds × write throughput in bytes per second. At a write throughput of 2 MB per second and an assumed maximum network interruption of 60 seconds, that yields a sensible backlog of at least 120 MB, or more realistically 200 to 256 MB with a safety margin. This number should not be guessed but derived from real INFO statistics on actual write throughput and observed network interruption durations.
# redis.conf: sizing the replication backlog
# Rule of thumb: expected_outage_seconds * write_bytes_per_second
repl-backlog-size 256mb
repl-backlog-ttl 3600
# Measure actual write throughput to size the backlog correctly
redis-cli -p 6379 info stats | grep instantaneous_input_kbps
# Check current backlog usage and how much headroom remains
redis-cli -p 6379 info replication | grep -E "repl_backlog_active|repl_backlog_size|repl_backlog_histlen"
The repl-backlog-ttl parameter determines how long the backlog is kept in memory after the last replica disconnects, before it gets discarded. A value that is too low unnecessarily gives up partial resync capability for replicas that disconnect briefly and reconnect quickly. It is also important to note that the backlog is only created once at least one replica has connected, a freshly started master with no replica ever connected has no active backlog in memory yet.
5. replica-read-only and write protection on replicas
By default, the replica-read-only parameter in Redis is set to yes, meaning replicas reject write commands from direct clients. This is a deliberate safety measure: if clients accidentally or intentionally wrote data directly to a replica, those changes would be silently overwritten at the next replication sync as soon as the master sends data again, which can cause confusing, hard to trace data loss.
There are legitimate reasons to set replica-read-only to no, for example to store temporary, non-replicated data on a replica that should never flow back to the master. This practice, however, is an anti pattern in the vast majority of cases and should only be used with full understanding of the consequences, since such writes are lost without a trace at the next full resync. In the overwhelming majority of setups, replica-read-only yes should stay unchanged.
# redis.conf on every replica: enforce read-only by default
replica-read-only yes
# Attempting a write against a read-only replica fails clearly
redis-cli -p 6380 set foo bar
# (error) READONLY You can't write against a read only replica.
# Verify the setting live on a running replica
redis-cli -p 6380 config get replica-read-only
# 1) "replica-read-only"
# 2) "yes"
# Route write traffic exclusively to the master in application code
# Reads may be routed to replicas for load distribution
6. Detecting and minimizing replication lag
Replication lag describes the delay between a write on the master and its visibility on a replica. Since Redis replication is asynchronous, this lag practically always exists, usually in the range of a few milliseconds on stable networks, but it can grow to seconds or more under network problems, overloaded replicas, or very large individual commands. Applications that read from a replica immediately after a write, for example in a read after write pattern, can receive stale data because of this lag.
The most reliable way to measure lag is comparing the master's master_repl_offset with the slave_repl_offset that each replica reports via INFO replication on the master. The difference between these two offsets, converted using the known write throughput, gives a good estimate of the time delay. If this difference keeps rising instead of fluctuating, it indicates the replica can no longer keep up with the master's processing speed, often a sign of insufficient hardware resources on the replica side.
# On the master: see offset and lag reported for every replica
redis-cli -p 6379 info replication
# slave0:ip=10.0.1.12,port=6379,state=online,offset=884213,lag=0
# slave1:ip=10.0.1.13,port=6379,state=online,offset=884198,lag=1
# Compute lag manually from offsets if lag=0 looks suspicious
# lag_bytes = master_repl_offset - slave_repl_offset
redis-cli -p 6379 info replication | grep master_repl_offset
For applications that need consistent reads immediately after a write, the most pragmatic solution is to route critical reads directly against the master instead of a replica, rather than attempting to eliminate replication lag entirely. Full elimination would require synchronous replication, which Redis does not offer by default and which noticeably costs latency and throughput when enforced via WAIT.
7. Diskless replication and RDB transfer
During a classic full resync, the master first writes an RDB snapshot to local disk and then transfers that file to the replica. For large datasets, that means extra I/O load and latency from the detour through disk. Diskless replication, enabled via repl-diskless-sync yes, skips this step: the master builds the RDB snapshot directly in memory and streams it to the replica immediately, without any intermediate storage.
The repl-diskless-sync-delay parameter introduces a short, configurable delay before the diskless transfer starts, allowing several newly connected replicas to share the same snapshot stream instead of generating a separate snapshot for each replica. That is particularly relevant when several replicas are newly set up at the same time, for example after a coordinated infrastructure update, since it considerably reduces CPU load on the master.
# redis.conf: diskless replication configuration
repl-diskless-sync yes
repl-diskless-sync-delay 5
repl-diskless-load disabled
# On the replica side, diskless loading avoids writing the
# incoming RDB to disk before applying it (Redis 6+)
# repl-diskless-load on-empty-db # safe default for most setups
On the replica side, repl-diskless-load controls whether the incoming RDB stream is likewise loaded directly without intermediate storage on disk. The on-empty-db setting is usually the safest choice, since it only allows diskless loading when the replica holds no data yet, preventing a failed load from putting an already functioning replica into an inconsistent state.
8. Chained replication: sub-replicas
Redis allows a replica to itself act as a master for further replicas, a pattern known as chained replication or sub-replicas. Instead of ten replicas connecting directly to the primary master and consuming its network bandwidth and CPU for serializing the replication stream, for example only two replicas connect directly to the master, and each of those two in turn serves several sub-replicas.
This pattern considerably reduces load on the primary master, especially in setups with many geographically distributed replicas, for example when replicas are needed across several regions and bandwidth between regions is limited. The trade off: sub-replicas inherit the replication lag of their parent replica in addition to that replica's own lag to the master, so the effective delay can accumulate across several levels. For most setups with a manageable number of replicas, direct replication from the primary master remains the simpler and more advisable choice.
Mironsoft
Redis operations, replication tuning, and infrastructure consulting
Frequent full resyncs instead of fast partial resyncs?
We analyze your write throughput, size the replication backlog correctly, and configure diskless replication so replicas resynchronize in seconds instead of minutes after network issues.
Backlog sizing
Correctly calculating backlog size from real throughput and outage data
Lag monitoring
Making replication lag measurable and setting sensible alert thresholds
Topology consulting
Evaluating chained replication and diskless sync for your infrastructure
9. Monitoring replication with INFO replication
The INFO replication command is the central source for every metric related to Redis replication, both on the master and on every replica. On the master it shows, for each connected replica, its IP, port, connection status, current offset, and the reported lag in seconds. On the replica side, the same command shows the role, the master's address, the connection status to the master, and the replica's own replication offset.
| Metric | Where visible | Meaning |
|---|---|---|
| master_repl_offset | Master | Current write position in the replication stream |
| slave_repl_offset | Replica | Last position processed by the replica |
| sync_full | Master | Count of expensive full resyncs |
| sync_partial_ok | Master | Count of cheap partial resyncs |
| repl_backlog_histlen | Master | Amount of data currently held in the backlog |
A production ready monitoring setup should continuously derive at least four things from INFO replication and INFO stats: the number of connected replicas relative to the expected count, the reported lag per replica, the ratio of sync_full to sync_partial_ok over time, and the utilization of the replication backlog relative to its configured size. Together, all four values give a reliable picture of whether replication is running stably or a problem is brewing.
10. Summary
Understanding master-replica replication in detail mostly means internalizing the PSYNC protocol and its dependency on the replication backlog. A correctly sized backlog is the difference between an invisible partial resync after brief network problems and an expensive full resync that takes minutes and noticeably increases production load. The formula of expected outage duration times write throughput provides a solid basis for that sizing.
replica-read-only should stay enabled in nearly every setup to prevent accidental writes that get lost at the next sync. Diskless replication reduces I/O load for large datasets, and regularly monitoring sync_full, sync_partial_ok, and the reported lag per replica surfaces problems before they turn into real outages or stale read responses in production.
Master-Replica Replication in Detail: The Essentials at a Glance
PSYNC enables partial resync
Replication ID and offset allow catching up on just the missing commands after interruptions.
Size the backlog correctly
Outage duration times write throughput as the formula, with a safety margin for production.
Keep replica-read-only enabled
Prevents writes that get silently lost at the next sync.
Monitor sync_full vs. sync_partial_ok
Directly shows whether the backlog configuration matches real network stability.