github valkey-io/valkey 9.2.0-rc1

pre-release7 hours ago

Valkey 9.2.0-rc1 - Released Wed 16 September 2026

Upgrade urgency LOW: This is the first release candidate of Valkey 9.2.0.

Behavior Changes

  • Active expiration of keys and hash fields now increments the dirty counter, so save points (and thus BGSAVE) may trigger more often by @enjoy-binbin (#3118)

New Features and Enhanced Behavior

  • Add ACL DIGEST command that returns a fingerprint of the ACL rules currently in effect, useful to verify what ACL LOAD applied by @melancholictheory (#4446)
  • Add forkless RDB snapshots, opt-in via the new forkless-infrastructure-enabled and bgsave-default-method configs, with new INFO persistence fields reporting the save method and progress by @JimB123 (#4460)
  • Add the XACKDEL and XDELEX stream commands with KEEPREF, DELREF and ACKED modes to acknowledge and delete messages once consumer groups no longer need them by @nickiaq (#4629)
  • Support a secondary server certificate via tls-alt-cert-file, tls-alt-key-file and tls-alt-key-file-pass, e.g. a post-quantum certificate alongside RSA, with matching INFO TLS fields by @pkhartsk (#3717)
  • Add ACL roles: named, reusable sets of ACL selectors managed with ACL SETROLE/DELROLE/GETROLE/ROLES and assigned to users with role:<name>, in commands, the ACL file and valkey.conf by @yang-z-o (#3967)
  • Add a maxmemory-scripts config to limit memory used by cached EVAL scripts, and mark SCRIPT LOAD as DENYOOM so it respects the global maxmemory limit by @enjoy-binbin (#866)
  • Add Path Hash, a new radix-tree-backed data type with PH* commands for exact lookup, longest-prefix matching, and prefix traversal over binary-safe paths by @yangbodong22011 (#4506)
  • Support whole-stream LZ4 compression of RDB files via the new rdbcompression lz4 option; the default per-string LZF behavior is unchanged by @sarthakaggarwal97 (#3531)
  • Add server-side hot key detection with new HOTKEYS GET/RESET commands, enabled by setting hotkeys-top-k by @alon-arenberg (#3708)
  • Add optional replication throttling (repl-throttling-enabled) that slows client writes when a replica falls behind, avoiding disconnects and full syncs by @harrylin98 (#4356)
  • Prioritize system-critical events (cluster heartbeats, replication, slot migration) over heavy client traffic, tunable via the new priority-preemptive-poll-interval-us config by @satheeshaGowda (#4076)
  • Reserve connection slots for administrative clients: connections from the CIDR ranges listed in the new priority-subnets config are tagged as prioritized, maxclients-reserved caps normal clients at maxclients minus that many slots, and INFO clients reports connected_priority_clients by @satheeshaGowda (#4005)
  • Add INCREX command to atomically increment a key by an integer or float while setting its expiration, with NX/XX conditions by @GavinDmello (#3253)

Performance and Efficiency Improvements

  • Speed up radix tree lookups and inserts by using SIMD-optimized memchr() for child-edge search by @charsyam (#3472)
  • Improve replica processing speed by parsing multiple commands from the replication stream at once by @enjoy-binbin (#3597)
  • Reduce memory usage by sharing pubsub pattern and WATCH key objects across clients subscribing to or watching the same name by @enjoy-binbin (#4072)
  • Large sorted sets are now backed by a B+ tree instead of a skiplist; OBJECT ENCODING reports btree instead of skiplist by @ranshid (#4359)
  • Save the cluster config file from a background thread when cluster-config-save-behavior is best-effort, avoiding main-thread latency spikes from slow disk I/O by @enjoy-binbin (#2555)
  • Speed up HMGET, SMISMEMBER and ZMSCORE on large hashtable-encoded keys with batched lookups that overlap memory accesses by @chzhoo (#4017)
  • Extend memory prefetching to hash, set and sorted set member lookups when io-threads are enabled, improving performance for 30 field/member commands on large keys by @roshkhatri (#3940)
  • MEMORY PURGE now also releases free pages from the glibc main arena back to the OS, reclaiming memory held by libc-internal allocations by @webbsssss (#3640)
  • Speed up command propagation to replicas by batching each command's RESP frame into a single replication buffer write by @hpatro (#4044)
  • Reduce lseek system calls during disk-based replication by seeking only when a write blocks or is partial by @enjoy-binbin (#4053)
  • Reduce event-loop overhead by refreshing cached daylight-saving info once per second instead of on every wakeup by @hpatro (#4086)
  • Speed up keyspace event notifications by skipping work when there are no subscribers and avoiding unnecessary allocations by @enjoy-binbin (#4285)
  • Speed up exact XTRIM MAXLEN = 0 by about 2.5x by clearing the whole stream in one step instead of removing entries individually by @sarthakaggarwal97 (#4161)
  • Cluster bus reads, writes, and inbound TLS accepts can now run on the shared I/O thread pool, with new CLUSTER INFO offload statistics by @hpatro (#3438)
  • Small hashes with field expiration now use the memory-efficient listpack encoding instead of always converting to a hashtable by @frostzt (#3212)
  • Reduce per-command overhead by skipping post-command bookkeeping when no propagation, module, or invalidation work is pending by @ahmetalicc (#4257)

Bug Fixes

  • MODULE LOAD is now rejected during async replication loading and atomic slot migration to avoid unexpected module behavior by @KIvanow (#3039)
  • Reject CLUSTER ADDSLOTS/DELSLOTS/ADDSLOTSRANGE/DELSLOTSRANGE/FLUSHSLOTS on replicas, preventing an assertion failure on a later CLUSTER REPLICATE by @enjoy-binbin (#4020)
  • Fix a crash when processing a heartbeat from a cluster node whose role is locally unknown, such as after loading an incomplete nodes.conf by @enjoy-binbin (#4091)
  • Fix wrong results or debug-build assertions in cluster mode when the server inspects keys outside the executing command's slot, such as WATCHed keys checked during EXEC by @nitaicaro (#4380)
  • Fix stream commands that mutate consumer-group or PEL state (XGROUP, XSETID, XREADGROUP, XACK, XCLAIM, XAUTOCLAIM) not triggering WATCH and client-side tracking invalidation by @Tarte12 (#3459)
  • Fix a server crash on FUNCTION DELETE or FUNCTION LOAD REPLACE after loading a library with function names differing only in case by @madolson (#3925)
  • Client-side tracking no longer records routing-only tokens such as the CLUSTERSCAN cursor as tracked keys by @nmvk (#3699)
  • Reject malformed slot entries in the cluster config file as a corrupt config instead of asserting or invoking undefined behavior by @enjoy-binbin (#4100)
  • Fix a TLS busy loop that consumed 100% CPU when a connection's read or write handler was removed while OpenSSL was waiting for the opposite event by @yairgott (#3510)
  • Client eviction no longer disconnects extra clients when a large client's close is deferred but its memory is already scheduled to be freed by @dhruv2x (#4152)
  • Fix a crash caused by a NULL pointer dereference when all timer events in an event loop are pending deletion by @royenheart (#4351)
  • Rework iteration over clients blocked on ready keys to simplify and harden an earlier use-after-free fix by @enjoy-binbin (#4472)
  • Fix a race in RDB string compression that could produce corrupt, unloadable RDB files when compression runs concurrently, without increasing copy-on-write by @dubey02 (#4539)
  • Fix dropped field TTLs and a possible crash when loading a hash with field expiration converts it to a hashtable mid-load (e.g. via RESTORE) by @madolson (#4669)
  • Reject a repeated CLUSTER SYNCSLOTS ESTABLISH on the same connection, which could lead to a use-after-free crash on disconnect by @Pyolar (#4670)
  • Fix wrong ZCOUNT results and incorrect ZREMRANGEBYSCORE deletions when members sharing a boundary score span multiple btree leaves by @rainsupreme (#4554)
  • Fix SORT key extraction so a STORE destination named like an option can no longer bypass ACL checks and write to an unauthorized key by @madolson (#4665)

Command and API Updates

  • MOVE accepts a new optional REPLACE argument to overwrite an existing key in the destination database by @bandalgomsu (#2993)
  • WAIT and WAITAOF now reject numreplicas values that are negative or exceed INT_MAX, fixing an integer overflow that broke blocking by @enjoy-binbin (#3407)
  • Add CONFIG INFO subcommand returning config metadata such as type, flags, valid enum values and numeric ranges by @nitaicaro (#3050)
  • Add the IFNE option to SET to set a key only when its current value differs from the given comparison value by @arshidkv12 (#3105)
  • Add IFEQ, IFNE, NX and XX conditions to EXEC, enabling optimistic locking for multi-key transactions without WATCH by @bandalgomsu (#4019)
  • Add an optional XX flag to SISMEMBER that returns -1 when the key does not exist, distinguishing a missing key from a missing member by @li-benson (#2972)
  • Handle NOT_KEY key-specs more defensively so COMMAND GETKEYS and ACL key checks consistently treat routing-only tokens as non-keys by @enjoy-binbin (#3675)
  • Fix DEBUG HELP to show the correct DELAY-RDB-CLIENT-FREE-SECONDS name and document the SET-DISABLE-DENY-SCRIPTS subcommand by @xiejing-dev (#4099)
  • Add XX option to the ZRANGE family of commands to distinguish a non-existent key (nil) from an empty result by @youngmore1024 (#2978)
  • Fix the reply schemas of the ZRANGE family of commands to allow the null reply returned with the XX option by @murphyjacob4 (#4275)
  • Fix the XPENDING reply schema to describe the summary reply returned when a consumer group has no pending messages by @sarthakaggarwal97 (#4653)

Cluster and Replication

  • Cluster replicas now redirect keyless commands like SCAN and FLUSHDB to the primary for clients with CAPA REDIRECT that have not sent READONLY by @yanamolo (#3505)
  • Changing cluster-require-full-coverage via CONFIG SET now updates the cluster state immediately instead of waiting for the next cron cycle by @enjoy-binbin (#3676)
  • Fix CLUSTER BUMPEPOCH getting stuck when a dead node holds an equal or abnormally high config epoch; a single bump now overtakes it by @enjoy-binbin (#4092)
  • Replicas now retry PSYNC when the primary replies -BUSY instead of downgrading to legacy SYNC, which broke WAIT, PSYNC and FAILOVER by @enjoy-binbin (#4140)
  • SYNC/PSYNC from a replica with a down primary link now consistently returns -NOMASTERLINK, avoiding an unnecessary full sync fallback by @enjoy-binbin (#4148)
  • Add cluster-replica-priority config so operators can rank which replicas are preferred during automatic cluster failover by @enjoy-binbin (#2204)
  • Speed up recovery from split-vote failover elections with a new FAILOVER_AUTH_NACK message that lets a replica detect an unwinnable election and immediately retry with a higher epoch by @enjoy-binbin (#3833)
  • Add optional per-target AUTH username password to CLUSTER MIGRATESLOTS, with credentials redacted from the slow log and MONITOR by @nemtsv (#3538)
  • Compress the full-sync RDB payload with LZ4 when rdbcompression lz4 is set and every attaching replica advertises support, reducing sync bandwidth with safe fallback to plaintext by @roshkhatri (#4075)
  • Add an if-empty value to cluster-replica-no-failover so a replica that has never received data from its primary refuses automatic failover, preventing silent data loss by @enjoy-binbin (#4425)
  • Add optional LZ4 streaming compression for steady-state replication via the new repl-compression config, negotiated per replica so older or opted-out replicas keep receiving plaintext by @roshkhatri (#3853)
  • Fix CLUSTERSCAN fingerprints to derive from the hash-seed config so cursors survive failover between nodes sharing a seed by @enjoy-binbin (#3679)
  • Replicas trigger a failover check immediately when cluster-replica-no-failover is disabled at runtime, instead of waiting for the next cron tick by @enjoy-binbin (#3827)
  • Validate node IDs and shard IDs received in cluster messages before applying them, dropping the link on invalid data to protect cluster state by @enjoy-binbin (#4065)
  • Drop the cluster link when a gossip section contains invalid node IDs, instead of keeping the connection to a corrupted sender alive by @enjoy-binbin (#4077)
  • Persist nodes.conf promptly when a node's address is updated through the gossip section by @enjoy-binbin (#4089)
  • Reject malformed node IDs in the open-slots RDB aux field instead of creating an illegal cluster node by @enjoy-binbin (#4098)
  • Strip the redundant LIMIT option when rewriting XADD/XTRIM for propagation, so the rewritten command is valid for tools that replay it by @cjx-zar (#4063)
  • Persist non-default cluster-replica-priority to nodes.conf so it survives restarts instead of waiting for the next gossip round by @enjoy-binbin (#4454)
  • Clear a stale primary-failure gossip flag on replicas so later failovers don't incorrectly skip the election delay by @charsyam (#4533)
  • Fix a node staying stuck in PFAIL when its PING is lost while the peer's own traffic keeps the cluster link alive by @enjoy-binbin (#4171)
  • CLUSTER SYNCSLOTS FINISH now rejects clients outside the slot migration stream, preventing misuse of the import state machine by @enjoy-binbin (#4330)

Configuration

  • commandlog-request-larger-than and commandlog-reply-larger-than now accept memory units such as 10mb by @enjoy-binbin (#2648)
  • cluster-announce-ip now must be a valid IP address or hostname, rejecting values like ip:port that broke cluster bus addressing by @AlisinaDevelo (#4055)
  • Reject an empty tls-ca-cert-dir at startup and CONFIG SET time instead of silently accepting it and failing every client handshake later by @yang-z-o (#3522)
  • Document the database-level ACL rules (db=, alldbs, resetdbs) in valkey.conf and clarify the reset rule description by @enjoy-binbin (#3808)
  • CONFIG REWRITE now preserves module load order, so modules with dependencies load correctly after a restart by @Taeknology (#3769)
  • Document in valkey.conf that unixsocketgroup requires the chown syscall to be allowed under syscall-filtering sandboxes by @moko-poi (#3730)

Module API Changes

  • Add ValkeyModule_ScanKeyRawBorrowed to scan hash, set and sorted set keys without allocating a string per element by @KarthikSubbarao (#4403)
  • Fix loading of legacy Redis modules that export RedisModule_OnLoad via a linker version script by @roshkhatri (#3374)
  • Module global defrag callbacks now receive a time limit and a resumable cursor, making ValkeyModule_RegisterDefragFunc usable for large module data by @Aksha1812 (#4487)
  • Add ValkeyModule_IncrExternalMemory/DecrExternalMemory so modules can report memory allocated outside the server allocator toward used_memory and maxmemory by @bandalgomsu (#4128)
  • Correct ValkeyModule_FreeModuleUser, ValkeyModule_ACLAddLogEntry and ValkeyModule_ACLAddLogEntryByUserName declarations to return int as implemented, fixing undefined behavior on targets with strict call signature checks by @rainsupreme (#4676)

Observability and Logging

  • Client memory usage now includes watched key and pubsub channel/pattern names, making it visible in CLIENT INFO tot-mem and counted for maxmemory-clients by @enjoy-binbin (#3362)
  • CONFIG RESETSTAT now also resets the IO-thread prefetch and ACL access-denied statistics by @enjoy-binbin (#2891)
  • Latency report now recommends 'madvise' for disabling Transparent Huge Pages, consistent with the startup check by @enjoy-binbin (#3947)
  • Log when a cluster primary ignores an MFSTART manual failover message from an unknown node or a non-replica, helping diagnose failover timeouts by @enjoy-binbin (#4058)
  • Log a warning when a TLS certificate has an invalid notBefore or notAfter field on OpenSSL 4.0 builds by @pkhartsk (#4064)
  • Gossip corruption warnings now log the actual entry with the invalid node ID instead of the first gossip entry by @enjoy-binbin (#4101)
  • Produce crash stack traces on musl-based systems like Alpine Linux via a libbacktrace fallback by @hanxizh9910 (#3581)
  • Always log the "possibly failing" notice when a node enters PFAIL, including on voting primaries by @enjoy-binbin (#4186)
  • EXEC transactions are now recorded in the slowlog and commandlog when their total execution time crosses the threshold by @michellee-10 (#4267)
  • Add last_successful_sync_duration_ms to INFO replication, reporting how long the replica's last full sync took by @satheeshaGowda (#4197)
  • Fix signal mask parsing on 32-bit systems so the crash handler can collect thread stack traces by @sarthakaggarwal97 (#4415)
  • Add total_cluster_links_established_inbound/outbound counters to CLUSTER INFO to help detect cluster link flapping by @enjoy-binbin (#4169)
  • RDMA connection and resource setup failures are now logged with detailed system error information by @quanyeyang (#4586)
  • Include the LRU list's duplicated script SHA copies in EVAL script memory reporting (used_memory_scripts_eval) by @enjoy-binbin (#4587)
  • Log the module version alongside the module name when a module is loaded, so the loaded version is visible in the log by @enjoy-binbin (#4566)
  • Detect changes to the alternate TLS key file (tls-alt-key-file) so certificate auto-reload picks them up by @pkhartsk (#4663)
  • Report tls_server_cert_serial and expiry INFO fields for the certificate actually loaded from tls-cert-file instead of whichever one OpenSSL slots first by @madolson (#4664)

CLI and Tools

  • valkey-cli reads the VALKEYCLI_HOST and VALKEYCLI_PORT environment variables to set the default host and port by @Dietr1ch (#3402)
  • valkey-benchmark can load CSV/TSV datasets and inject their fields into commands via __field:name__ placeholders by @VoletiRam (#2823)
  • valkey-cli supports the VALKEYCLI_USER environment variable as an alternative to the --user option by @jdheyburn (#4126)
  • valkey-cli --rdb now exits with an error instead of reporting success when trimming the RDB EOF marker fails, avoiding a silently corrupt file by @gluxier (#3945)
  • Fix valkey-benchmark crash (out-of-bounds read) when a repeat count is given with no command following it by @lightsigma96 (#4142)
  • valkey-benchmark -r now accepts keyspace sizes above INT_MAX (up to 999,999,999,999) with proper input validation by @michellee-10 (#4252)
  • valkey-benchmark now rejects a repeat count with no command after it with a clear error instead of hanging forever sending zero requests by @dhruv2x (#4215)
  • valkey-benchmark multi-threaded mode scales further by removing cross-thread contention in key generation, latency recording, and counters by @rainsupreme (#4332)

Build and Tooling

  • Add REUSE-compliant machine-readable licensing with per-file license clarity, enabling SPDX SBOM generation and correct license detection by @zuiderkwast (#3968)
  • Fix clean or highly parallel builds failing with a missing release.h for valkey-cli, valkey-benchmark, and unit tests by @poiuj (#3683)
  • Use PRIVATE link dependencies in CMake so Valkey's CMake files can be safely integrated into other projects by @eifrah-aws (#3658)
  • Pass CPPFLAGS to bundled dependencies and the src Makefile so packaging hardening flags apply to the whole build by @Vonng (#4318)
  • Raise the minimum required CMake version to 3.24 to match features already used by the build by @Baraa-Hasheesh (#4232)

Contributors

Don't miss a new valkey release

NewReleases is sending notifications on new releases.