Redis 5 RC5 makes script effects replication the default
Redis 5 RC5 changes script replication and replica memory-limit defaults. It also fixes blocking reads of streams whose entries have all been deleted.
A replica does not need to execute the same program to reproduce the same database changes. Redis 5 RC5 makes replication of Lua script effects the default. The primary sends the commands produced by the script, so the replica can apply the resulting changes without rerunning the original script to derive them.
The September 6 release entry flags this as a breaking behavior change. The RC5 notes also announce that replicas ignore maxmemory by default. Together these decisions give the primary greater responsibility for defining the replicated dataset. They deserve attention even in an application that has no immediate use for Streams.
I value Redis for making operations explicit. These changes apply that preference to replication, where an instruction to reproduce a computation and an instruction to apply its result have different failure conditions. The release candidate makes the resulting behavior a default rather than requiring every application to opt into it.
The default changes in the server configuration
The effects-replication patch moves initialization of lua_always_replicate_commands into the server configuration and sets it to one. It also adds a configuration parser entry for lua-replicate-commands. The behavior change therefore comes from a server default, not a new Lua instruction that every existing script has to call.
Sending effects changes what replication and the append-only file need to represent. The record of the write operations can reproduce changes already chosen on the primary. Replaying a script instead asks another execution context to make those choices again. The distinction is especially relevant when script execution depends on state that may differ between contexts.
RC5 does retain an escape route in its configuration parser. The source accepts a yes-or-no value for lua-replicate-commands, so setting it to no clears the new default flag. That implementation detail is more precise than saying the old mode has become impossible. The release changes the default path while retaining configuration support for the flag.
A related read-only script patch addresses propagation when the server needs to supply a script body. It records the dataset dirty counter before execution. If execution produces no changes, the propagation path can use SCRIPT LOAD rather than execute the script again through EVAL.
The patch explains the practical reasons. Reexecuting a costly read-only script consumes replica CPU without producing dataset changes. An aborted script may also behave differently if executed again elsewhere. Loading the script preserves its availability without treating another execution as necessary evidence of the primary result.
Replicas follow eviction decisions made by the primary
The replica memory configuration patch explains the other default change. A replica ignores its own maxmemory setting while it remains a replica. The primary performs eviction and sends deletion commands as keys leave its dataset. After promotion, the server can apply its memory limit in its new role.
Independent eviction can make a replica lose keys that its primary still has. Following the primary eviction decisions instead preserves the intended relationship between their datasets. A local memory target and replicated consistency are therefore not interchangeable policies. Enforcing both independently can create disagreement about which keys should exist.
The supplied configuration commentary also explains the capacity consequence. Replicas may use more memory than the primary limit suggests, because buffers and data structures can have different sizes. Ignoring a limit does not create additional physical memory. An operator still has to provision a replica to accommodate the replicated workload and its local overhead.
I prefer this default for an ordinary replica because the role describes a copy of the primary dataset. A separately constrained writable replica is a different arrangement. RC5 retains a configuration option for that case, while its notes make clear that the operator is accepting a different policy.
An empty stream can retain a high last ID
The Streams correction addresses another distinction between recorded progress and present contents. A stream can have received entries and later lost all of them through deletion. Its last generated ID can remain greater than the ID supplied by a reader even though no entry is available to return.
The blocking-read patch adds a length check before choosing synchronous service. Previously, comparing the stream last ID with the requested position could make an empty stream qualify for an immediate response. The client then received an empty result instead of waiting for a new entry.
XREAD BLOCK 5000 STREAMS readings 0-0
For a stream whose entries have all been removed, this request should be able to wait for subsequent data. The patch requires a nonzero stream length as well as a later ID before the immediate-read branch qualifies. It updates both the ordinary read path and the corresponding consumer-group decision.
The underlying issue is that the last generated ID summarizes append history, while length describes currently available entries. The former cannot substitute for the latter when deciding whether to wake a blocked reader. RC5 repairs that condition while retaining IDs as the way readers express their progress through a stream.