Valkey Per-Key Memory Falls 37.5% from 7.2.14 to 9.1.1
Percona's Lucas Yang has published a benchmark that measures how much memory each Valkey release actually saves for small string keys, and the headline result is a 37.5% drop in per-key memory between Valkey 7.2.14 and 9.1.1. Valkey is an open source in-memory data store used for caching, sessions, real-time applications, ecommerce, ad tech and gaming. The same workload that averaged 102.48 bytes per key on 7.2.14 uses 64.02 bytes per key on 9.1.1, meaning the same hardware can store roughly 60% more of these small keys after the upgrade. The reduction is most useful for string-heavy environments, which are common in caching, sessions and authentication, real-time apps, ecommerce, ad tech and martech, and gaming.
To isolate the version effect, Yang tested five versions built from source: 7.2.14, 8.0.10, 8.1.9, 9.0.5, and 9.1.1. Every run used jemalloc 5.3.0 as the memory allocator, because different allocators can change memory usage independently of Valkey itself. The instances ran standalone rather than in cluster mode, with maxmemory set to 0 and persistence and eviction disabled by using save "" and appendonly no. The workload was generated with valkey-benchmark -t set -n 1000000 -r 1000000 -d 16, which sends one million SET commands with 16-byte values. Because the key space is also one million, random-key collisions leave about 63.2% of the operations as unique keys, roughly 632,000 keys, which matches the official Valkey benchmark methodology. The baseline memory of an empty instance was subtracted from each measurement so the numbers show true marginal bytes per key.
The results show that the biggest single jump came in version 8.1. On 7.2.14 the workload used 61.78 MB for 632,181 unique keys, or 102.48 bytes per key. Version 8.0.10 reduced that to 57.00 MB and 94.49 bytes per key, a 7.8% drop. Version 8.1.9 then cut memory to 43.43 MB and 71.98 bytes per key, a further 23.8% reduction compared with 8.0 and a cumulative 29.8% saving versus 7.2.14. Version 9.0.5 was essentially flat at 43.36 MB and 71.99 bytes per key (a 0.0% change from 8.1), while 9.1.1 dropped to 38.58 MB and 64.02 bytes per key, another 11.1% reduction and 37.5% less than the 7.2.14 baseline. For a 1 TB 7.2 deployment, the same data would occupy roughly 800 GB on 8.0, 640 GB on 8.1, and 630 GB on 9.1.
The first structural change appeared in Valkey 8.0. In 7.2, a dictionary entry (dictEntry) was a 24-byte structure holding three pointers: one to the key, one to the value, and one to the next entry in a hash collision chain. The key pointer referenced a separately allocated SDS (simple dynamic string) blob, so every lookup paid for an extra memory allocation and an extra memory hop just to read the key. Version 8.0 introduced embeddedDictEntry, which places the key bytes inline directly after the struct. The new layout is 16 bytes plus the key length, combining key and entry into a single allocation. The measured effect is 8 bytes less per key, one fewer memory hop on every lookup, and the change is automatic on upgrade with no configuration changes needed.
Valkey 8.1 delivered the largest single gain. In 8.0 the dictionary was a classic chained hash table, where reaching a value meant following a path of bucket to entry to key to value, four memory hops plus more for collisions. Version 8.1 rewrote this as a new hash table structure in which one bucket is exactly 64 bytes, the size of a CPU cache line (the small block of memory a processor loads at once). The bucket has an 8-byte metadata region that packs a has-child-bucket bit, seven filled-bits, and seven bytes of secondary hash. This lets most non-matching candidates be skipped without an extra memory access. The key and value are embedded in the same serverObject, shortening the lookup to roughly two hops, bucket to serverObject, and a hash collision usually stays within the same cache line. The dictEntry structure disappears entirely. The result is roughly 20 bytes less per key-value pair, and 30 bytes less for keys with a TTL. This accounts for the big drop from 8.0 to 8.1.
The final measured gain happened in 9.1. In earlier Valkey versions, embedded strings (embstr) still wasted an 8-byte pointer field that simply referenced the contiguous payload. Valkey 9.1 changed this for short strings: the string bytes are stored directly inline in the same 8 bytes normally used for the pointer. No pointer is needed, and no separate allocation is made for the value. The result is up to a 20% memory reduction for strings under 128 bytes, and the benchmark's key plus 16-byte value pairs sit in that range. Put together, the three structural changes show that Valkey's memory efficiency came from targeted low-level restructuring rather than a single sweeping rewrite.
Beyond the release-to-release savings, Yang also compared two ways of modeling the same data. Approach A stores each user attribute as a separate String key, for example SET user:1:name Alice, SET user:1:age 30, SET user:1:city Toronto, and SET user:1:score 100. Approach B stores one Hash key per user with four fields, such as HSET user:1 name Alice age 30 city Toronto score 100. For one million records, Approach A used 220 MB while Approach B used 100 MB, a 54% reduction. The gap exists because every key pays a fixed per-key overhead. Four separate keys pay that overhead four times, while one Hash key pays it once. The choice is not free, however. String keys natively support EXPIRE for per-key TTL, while Hash did not natively support field-level TTL before Valkey 7.4. Hash wins on atomic multi-field operations: a single HSET or HMGET can read or write several fields at once, while String needs multiple round trips. Hash also keeps all fields in one slot automatically for cluster locality, while String requires a manual hashtag to co-locate related keys. There is no universally correct answer; it depends on whether memory efficiency or per-field flexibility matters more for the use case.
Overall, the Percona tests quantify how Valkey's memory footprint for small string keys has fallen from 102.48 bytes to 64.02 bytes per key across five releases, with the largest step in 8.1 and a final inline-string optimization in 9.1. For teams operating Valkey at scale, a managed European cloud and data-infrastructure provider such as AEU Data can supply the monitoring, automated backups and high availability that make it safer to roll out and verify these memory reductions in production.