Redis 6.2 combines value access with explicit state changes
Redis 6.2 becomes stable with GETEX, GETDEL, COPY and stream recovery commands. The implementation shows how combined commands express application intent and propagate their actual state changes.
An application often needs a value and a related state change together. Reading a session may need to extend its lifetime. Reading a disposable value may need to remove it. Redis 6.2 gives those intents direct commands, alongside copying keys and recovering pending stream deliveries. The additions make the command vocabulary more complete while retaining specific rules about expiration and propagation.
The 6.2 release notes date general availability to February 22. The 6.2.0-tagged file includes the stable release and the preceding candidate changes. It describes the release as a collection of commands and improvements, many of which needed a longer candidate cycle or could not be replicated to an older server.
I have used Redis since its early releases, and I remain drawn to commands that express a small piece of application policy precisely. Combining a read with a specified state change is useful when that combination matches the actual requirement. The 6.2 additions deserve attention at that level, including how the server records the change after returning the value.
GETEX returns a value and changes its expiration
The command proposal introduces GETEX with expiration options. EX and PX specify a relative lifetime in seconds or milliseconds. EXAT and PXAT specify absolute Unix timestamps at the corresponding resolution. PERSIST removes an existing expiration. Only one option can be used at a time.
For example, an application that intentionally renews an existing string's lifetime can express the operation as:
GETEX session:example EX 300
The command returns the string and sets the requested expiration. It does not provide a value to create when the key is absent. The proposal says GETEX without an option behaves like GET, but the command is classified as capable of writing. A client cannot treat every invocation as a read-only operation merely because the reply contains a value.
The 6.2.0 string-command implementation makes the sequencing concrete. It parses options, looks up the key and verifies its string type. If an expiration is supplied, it validates that value before returning the bulk-string reply. Invalid expiration input therefore does not proceed through the normal successful expiration path.
The validation checks for nonpositive values and overflow when seconds convert to milliseconds. It also checks the resulting time after adding a relative lifetime to the current time. Those checks correspond to the stable release's note that overflowing expiration values now produce errors in several commands, including GETEX.
The implementation adds the value to the reply before deleting or expiring the key. For an absolute timestamp already in the past, it then deletes the key and rewrites the propagated operation as a deletion. That behavior distinguishes returning the existing value from leaving it available after the command. An absolute deadline can request removal even though the caller receives the value it just accessed.
Propagation records the mutation
GETEX is not propagated under its original name. The implementation rewrites it as the operation that changed state, such as PEXPIRE, PEXPIREAT or PERSIST. The already-expired absolute-time case uses DEL or UNLINK, depending on the configured deletion behavior. This connects the combined client command to the mutation replication and persistence need to represent.
That distinction is useful when interpreting logs or reasoning about replay. The returned string belongs to the requesting client's result. Replicas need the expiration or deletion change. Repeating the value read is unnecessary to represent that change, so the implementation separates the public command's combined intent from the propagated operation.
For PERSIST, propagation occurs only when an expiration was actually removed. The source checks the return value of removeExpire before marking the key modified and rewriting the command. The implementation therefore distinguishes a requested change from a change that took effect. That is a small detail with a direct consequence for how much work the mutation path records.
I like this aspect of the design because it makes the contract inspectable. A command can have a convenient client-facing form while still recording the precise state transition the database must retain. The source supplies the behavior for expiration, persistence removal and already-past deadlines separately.
GETDEL expresses a different lifecycle
The same proposal adds GETDEL for retrieving a string and deleting its key. The implementation first uses the normal string-get path. If that path reports a type error, the function returns. A successful deletion then uses synchronous or asynchronous removal according to the configured user-deletion setting.
When a key is deleted, the propagated command becomes DEL or UNLINK. As with GETEX, the public operation's value reply is separate from the mutation that replicas need. The command also signals the modified key and records a deletion event in its notification path.
This operation is appropriate only when reading is intended to consume the stored value. It does not add an acknowledgment protocol for subsequent work performed by the application. The state transition ends at retrieving and removing the key. A workflow that requires pending deliveries and later recovery has a different requirement, which the stream commands address.
COPY adds a key-level operation
The COPY proposal defines a source key, destination key, optional destination database and a REPLACE option. Those arguments express a key-level copy without making the client retrieve a value and choose a type-specific way to reconstruct it. The release notes also add a module data-type callback for copying.
The module callback matters because Redis can hold data types whose internal representation is supplied by a module. Adding the server command therefore includes an extension point for those types. The release is not limited to giving strings a second name through client code. Its API work accounts for copying values represented by modules as well.
The optional destination database and replacement behavior remain explicit parts of the request. They should not be hidden by a wrapper that assumes every copy is allowed to overwrite. A server command reduces the amount of application logic needed to express the operation while leaving the destination and replacement decision with the caller.
Stream recovery retains consumer-group state
The release includes XAUTOCLAIM, added during RC2. Its proposal combines discovery and claiming of pending stream entries that meet an idle threshold. It returns a stream-ID cursor for continuing the scan, with 0-0 indicating completion. The receiving consumer is named in the command.
This is a different form of recovery from retrieving and deleting a string. XAUTOCLAIM operates within existing stream consumer-group state. Its minimum idle time and continuation cursor remain decisions the client must handle. Combining the discovery and transfer step removes one exchange without eliminating the recovery policy or the need to continue scanning.
The proposal explains the cursor design partly through the memory cost of an alternative idle-time index. It estimates substantial additional overhead for maintaining that structure. The chosen API retains incremental scanning instead. That is a concrete tradeoff behind a command that could otherwise look like an arbitrary convenience addition.
Stability includes existing behavior changes
The stable release also contains a security correction for 32-bit builds when the maximum bulk-input limit is raised substantially. Its notes identify CVE-2021-21309 and say the default 512 MB limit is safe on all platforms. The problematic configuration permits large requests to reach integer-overflow cases that can cause heap corruption. This qualification determines the urgency described in the release notes.
Other changes affect existing deployment assumptions. The accumulated notes describe startup failure when a required bind address is unavailable, changes to command-line handling of the save configuration, and atomic configuration rewrites that require directory write access. These are operational behaviors to account for alongside adopting new commands.
Administration clients gain a related improvement in error handling. The accumulated release notes add a redis-cli -e option to return a failure exit code when command execution fails. This distinguishes successful process communication from successful command execution for scripts that opt into the behavior. It is a client-tool change, separate from the new server commands, and supplies a more direct result for automation invoking them.
Redis 6.2's combined operations therefore have specific boundaries. GETEX returns a string and applies an expiration decision, while GETDEL consumes a stored string. Their implementation propagates the mutation that occurred. Stream recovery retains a cursor and pending-entry policy, which gives applications a separate mechanism when removal alone cannot represent the intended lifecycle.