JusDB
Free DB Audit
NoSQL Databases

Sizing Bloom Filters on Valkey: The 128 MB Cap, Scaling Math, and VALIDATESCALETO

Size valkey-bloom filters before they hit the 128 MB per-filter cap: bits-per-item math, how scaling filters grow, NONSCALING vs scaling, and VALIDATESCALETO checks.

JusDB Team
Published November 1, 2026
Updated November 10, 2026
20 min read

A Bloom filter on Valkey looks free until the day BF.ADD returns ERR operation exceeds bloom object memory limit. In valkey-bloom 1.0.1, the module behind the BF.* commands, every filter is one key with a per-key memory cap of 128 MB. The first BF.ADD on a new key quietly creates a filter sized for 100 items, which then doubles each time it fills. Each doubling adds memory, adds hash checks to every lookup, and loosens the overall false-positive rate. A default filter stops growing at 26,214,300 items. A filter you sized yourself can hold several times that in less memory. This guide gives the sizing math, how scaling filters grow and stop, the NONSCALING and VALIDATESCALETO options, replication and persistence, and two patterns.

TL;DR
  • A filter needs about 9.6 bits per item at a 1% false-positive rate and 14.4 bits at 0.1%. Multiply by the item count before you create it.
  • bf.bloom-memory-usage-limit defaults to 134,217,728 bytes (128 MB) per filter. You can change it with CONFIG SET, and every create and scale-out is checked against the current value.
  • Scaling filters add a sub-filter twice the size of the last one, with half its false-positive rate. The combined rate can approach twice the rate you asked for, and every lookup that misses checks every sub-filter.
  • If you know the item count, reserve it up front, with NONSCALING when the count is fixed. Use BF.INSERT ... VALIDATESCALETO n to reject a scaling filter that can never reach n items.
  • Run valkey-bloom 1.0.1, which fixes CVE-2026-21864, and set the same memory limit on every node, because the RDB loader enforces it too.

Scope and review date: November 2026. This post covers valkey-bloom 1.0.1 on Valkey 8.1 and later (8.0 needs the module built with its valkey_8_0 feature flag), the version that valkey-bundle 9.1.4 (Valkey 9.1.3) ships. Defaults, error strings and commands were checked against the valkey.io documentation and the module's 1.0.1 source on 10 November 2026. The sizing figures are arithmetic from the module's own formulas, not measurements: the commands were not run in a lab, so confirm each number with BF.INFO on your own server.


How many bits and hash functions does a Bloom filter need?

A Bloom filter is a bit array plus k hash functions. Adding an item sets k bits, and a lookup reports "maybe present" only if all k bits are set. A filter can give a false positive, but never a false negative. The valkey.io Bloom filter topic describes the behaviour. The sizing comes from the Rust bloomfilter crate that valkey-bloom 1.0.1 builds on, which uses the textbook formulas:

  • bits per item = −ln(p) ÷ (ln 2)², where p is the false-positive rate;
  • bitmap bytes = ⌈n × −ln(p) ÷ (8 × (ln 2)²)⌉ for n items;
  • hash functions k = round(bits per item × ln 2), with a minimum of 1.
bash
# Worked arithmetic: bytes and hash count for n items at rate p
python3 -c '
import math
n, p = 50_000_000, 0.001
bits = -math.log(p) / math.log(2) ** 2
print(f"bits/item={bits:.3f} k={round(bits * math.log(2))}")
print(f"bitmap bytes={math.ceil(n * bits / 8):,}")'
# bits/item=14.378 k=10
# bitmap bytes=89,859,923

Interpretation: 50 million items at 0.1% need about 85.7 MiB of bitmap and 10 hash functions. valkey-bloom adds a few hundred bytes of fixed overhead per filter: 264 bytes for a one-filter object, by the 1.0.1 struct sizes. That is why the documented default filter (100 items at 1%) reports a Size of 384 bytes: a 120-byte bitmap plus 264.

False-positive rateBits per itemHash functions in valkey-bloomBytes per million items
1% (0.01)9.58571,198,133
0.1% (0.001)14.378101,797,199
0.01% (0.0001)19.170132,396,265

Each tenfold cut in the false-positive rate costs another 4.8 bits per item. The RedisBloom BF.RESERVE page gives the same bits per item but rounds the hash count up, so it lists 14 hashes at 0.01% where valkey-bloom's crate rounds to 13.

What does BF.ADD create when the key does not exist?

BF.ADD, BF.MADD and BF.INSERT create a filter on first use from the module's defaults. The topic page lists them: capacity 100 (bf.bloom-capacity), false-positive rate 0.01 (bf.bloom-fp-rate), expansion 2 (bf.bloom-expansion), tightening ratio 0.5 (bf.bloom-tightening-ratio) and a random seed (bf.bloom-use-random-seed). Expansion 2 means every implicit filter is a scaling filter.

bash
127.0.0.1:6379> BF.ADD seen:emails user@example.com
(integer) 1
127.0.0.1:6379> BF.INFO seen:emails CAPACITY
(integer) 100
127.0.0.1:6379> BF.INFO seen:emails MAXSCALEDCAPACITY
(integer) 26214300

Interpretation: the filter starts with room for 100 items and can grow to 26,214,300 before the next sub-filter would break the 128 MB cap. Changing the defaults with CONFIG SET affects only filters created afterwards. Existing keys keep the capacity, rate and expansion they were created with.

Creating the filter explicitly with BF.RESERVE key error_rate capacity avoids the default. Add NONSCALING or EXPANSION n, but not both: valkey-bloom rejects the pair, while RedisBloom's syntax lists both options.

Reserving a filter for one million items, then reading BF.INFO

Illustrative output: the values are computed from the valkey-bloom 1.0.1 sizing code, not captured from a server

valkey-cli: 127.0.0.1:6379
127.0.0.1:6379> BF.RESERVE seen:events 0.01 1000000OK127.0.0.1:6379> BF.INFO seen:events 1) Capacity 2) (integer) 1000000 3) Size 4) (integer) 1198397 5) Number of filters 6) (integer) 1 7) Number of items inserted 8) (integer) 0 9) Error rate10) "0.01"11) Expansion rate12) (integer) 213) Tightening ratio14) "0.5"15) Max scaled capacity16) (integer) 63000000

Read two fields: Size is the bytes held now, and Max scaled capacity is the ceiling under the current memory limit. The field layout follows the BF.INFO reference.

Do not copy the topic page's BF.INFO numbers

As of November 2026, the usernames example on the valkey.io Bloom topic (10,000 items at 0.001) shows a Size of 23,912 and a Max scaled capacity of 26,214,300. By the 1.0.1 formulas, those values should be about 18,236 and 20,470,000. The default-filter example also reports two items after one BF.ADD. Compute your own values, or read them from your server.

How does a scaling Bloom filter grow, and what does each step cost?

When the newest sub-filter is full, the next new item triggers a scale-out. valkey-bloom appends a sub-filter with capacity = previous capacity × expansion and false-positive rate = p × tighteningi, where i counts the sub-filters that already exist. With the defaults, the sub-filters hold 100, 200, 400 and so on items, at rates of 0.01, 0.005, 0.0025 and so on. Earlier sub-filters stay in the key and are checked on every lookup.

How a default scaling filter adds sub-filters

Capacity doubles and the false-positive rate halves at each step, until the next sub-filter would pass the 128 MB cap

Scale-out chain of a default valkey-bloom filter Step 1: sub-filter 1 holds 100 items at a 0.01 false-positive rate with 7 hash functions. Step 2: when it fills, sub-filter 2 is added with 200 items at 0.005 and 8 hash functions. Step 3: sub-filters 3 to 17 keep doubling capacity, from 400 to 6,553,600 items, and halving the rate. Sub-filter 18 holds 13,107,200 items at about 7.6 in 100 million with 24 hash functions, bringing the total to 26,214,300 items in about 102 MiB. Step 4: a 19th sub-filter would push the key past 128 MB, so the next new item is rejected with an error. Sub-filter 1 100 items, fp 0.01 7 hashes Sub-filter 2 200 items, fp 0.005 8 hashes Sub-filters 3 to 17 400 to 6,553,600 items doubling each time Sub-filter 18 13,107,200 items fp 7.6e-8, 24 hashes Sub-filter 19 refused: over 128 MB 1 2 3 4 Total after 18 sub-filters: 26,214,300 items about 102 MiB, up to 279 hash checks per miss

Lead: the last sub-filter is half the key. Sub-filter 18 alone needs about 53 MiB, allocated by the single BF.ADD that triggers the scale-out.

Each sub-filter adds three costs:

  • Memory per item rises. Each halving of the rate adds 1.44 bits per item, so sub-filter 18 uses about 34 bits per item against 9.6 in the first.
  • Lookups get slower. A lookup checks the sub-filters in turn and stops at the first one that matches. An item that is not in the filter, the common case for a guard, checks all of them. The topic page puts add and exists at O(N × K) for this reason.
  • The real false-positive rate drifts up. BF.INFO still reports the rate you set, 0.01. A miss can match any sub-filter, though, so once they fill, the combined rate approaches the sum 0.01 + 0.005 + 0.0025 + … , which stays just under 0.02. With tightening 0.5, the bound is twice the requested rate.

A scale-out can also be refused before the cap, if the next sub-filter's rate would round down to zero. valkey-bloom then returns ERR false positive degrades to 0 on scale out. With the default expansion, the memory cap comes first. In practice, you meet this error only with EXPANSION 1 or a very low tightening ratio.

Where is the 128 MB per-filter cap, and can you raise it?

The cap is the module configuration bf.bloom-memory-usage-limit, default 134,217,728 bytes, and it applies to each filter separately. valkey-bloom checks it when a filter is created and before each scale-out. An operation that would exceed it fails with ERR operation exceeds bloom object memory limit and changes nothing. It is not a server-wide budget: maxmemory still governs the instance, and the writing BF.* commands carry the deny-oom flag.

bash
127.0.0.1:6379> CONFIG GET bf.bloom-memory-usage-limit
1) "bf.bloom-memory-usage-limit"
2) "134217728"
127.0.0.1:6379> CONFIG SET bf.bloom-memory-usage-limit 268435456
OK

Interpretation: raising the limit to 256 MB takes effect immediately. The 1.0.1 code reads the current value on every create and scale-out, so a filter that was refused can grow again. A default filter under a 256 MB limit can reach 52,428,700 items in 19 sub-filters. The topic page says the limit exists to protect serialization performance.

To make it permanent, put it in valkey.conf after the loadmodule line. Keep comments on their own lines.

ini
loadmodule /usr/lib/valkey/libvalkey_bloom.so
# Per-filter memory limit: 256 MB
bf.bloom-memory-usage-limit 268435456

Interpretation: Valkey 9.1's config parser treats only lines that start with # as comments. For a module config, it joins every token after the name into the value. The valkey-bundle topic page's sample line bf.bloom-memory-usage-limit 134217728 # 128MB therefore passes 134217728 # 128MB as the value, which is not a number. The module path is valkey-bundle's.

A non-scaling filter is one bitmap, so its maximum size under a given limit is plain division. These figures are worked arithmetic from the 1.0.1 formulas.

False-positive rateLargest NONSCALING capacity under 128 MBExample that fails at create time
0.01112,022,240 itemsBF.RESERVE k 0.01 120000000 NONSCALING
0.00174,681,493 itemsBF.RESERVE k 0.001 100000000 NONSCALING (needs about 171 MiB)
0.000156,011,120 itemsBF.RESERVE k 0.0001 60000000 NONSCALING

Should you reserve a scaling or a NONSCALING filter?

The topic page's rule: use a non-scaling filter when the item count is known and fixed, and a scaling one when it is not. The panels load the same 26,214,300 items three ways, as worked arithmetic from the 1.0.1 formulas.

The same 26,214,300 items in three filters

Switch filters to compare memory, sub-filters, lookup cost and the real error rate at that fill level

Default (BF.ADD)

PropertyImplicit scaling filter
Created byBF.ADD key item (capacity 100, expansion 2)
Sub-filters18
Memory107,051,063 bytes (about 102 MiB)
Hash checks for a missUp to 279 (7 to 24 per sub-filter)
False-positive rate when fullUp to about 0.02
Next new itemERR operation exceeds bloom object memory limit

Sized start

PropertyScaling filter reserved at 1 million
Created byBF.RESERVE key 0.01 1000000
Sub-filters5 (holding up to 31,000,000)
Memory54,816,271 bytes (about 52 MiB)
Hash checks for a missUp to 45 (7 to 11 per sub-filter)
False-positive rate when fullUp to about 0.019
Next new itemAccepted; the filter can grow to 63,000,000

NONSCALING

PropertyFixed filter reserved at full size
Created byBF.RESERVE key 0.01 26214300 NONSCALING
Sub-filters1
Memory31,408,464 bytes (about 30 MiB)
Hash checks for a missUp to 7
False-positive rate when full0.01
Next new itemERR non scaling filter is full

Lead: reserving the right size up front uses less than a third of the memory of the default filter, with one fortieth of the hash checks and half the error rate.

A higher expansion does not always raise the ceiling. With a one-million start, EXPANSION 4 stops at 21,000,000 items, and the default expansion of 2 reaches 63,000,000. The bigger jumps reach a sub-filter that cannot fit sooner.

bash
127.0.0.1:6379> BF.RESERVE dedup:2026-11-10 0.001 5000000 NONSCALING
OK
127.0.0.1:6379> BF.RESERVE seen:urls 0.01 1000000 EXPANSION 2
OK
127.0.0.1:6379> BF.RESERVE bad 0.01 1000000 NONSCALING EXPANSION 2
(error) ERROR

Interpretation: the first command fixes the filter at five million items. The second scales from one million. The third fails because 1.0.1 accepts only one of the two options. The BF.RESERVE reference prose calls the option "SCALING <expansion rate>", but the keyword the module parses is EXPANSION.

How do you check that a filter can reach its target size?

VALIDATESCALETO n is an option of BF.INSERT, not BF.RESERVE. Before creating anything, valkey-bloom simulates the scale-outs for the capacity, rate, expansion and tightening on the command line. If n items cannot be reached under the current memory limit, or if the rate would degrade to zero first, the command is rejected and no key is created. It cannot be combined with NONSCALING, as the BF.INSERT reference states.

bash
127.0.0.1:6379> BF.INSERT seen:events CAPACITY 1000000 ERROR 0.01 VALIDATESCALETO 63000001
(error) ERR provided VALIDATESCALETO causes bloom object to exceed memory limit
127.0.0.1:6379> BF.INSERT seen:events CAPACITY 1000000 ERROR 0.01 VALIDATESCALETO 63000000
(empty array)
127.0.0.1:6379> BF.INFO seen:events MAXSCALEDCAPACITY
(integer) 63000000

Interpretation: by the 1.0.1 formulas, the ceiling for a one-million, 1% filter is 63,000,000 items in six sub-filters, so one item more is refused. The validation runs on the arguments you pass, not on an existing key. For a filter that already exists, read BF.INFO key MAXSCALEDCAPACITY, which recomputes the ceiling under today's limit. The other refusal reads ERR provided VALIDATESCALETO causes false positive to degrade to 0.

Sizing a Bloom filter before you create it

Seven steps, all safe to run on a live server; none needs a restart

  1. Estimate the items per key

    Count distinct items over the key's life: per day, per tenant or in total. Split the data across keys if one key would hold more than the cap allows.

  2. Choose the false-positive rate

    Price a wrong "maybe present". For deduplication it is a skipped item; for a guard it is one wasted database read.

  3. Compute the bitmap size

    Bytes are about n × −ln(p) ÷ 3.844. Add a few hundred bytes per sub-filter.

    python3 -c 'import math; n,p=5e6,0.001; \ print(math.ceil(n*-math.log(p)/(8*math.log(2)**2)))'
  4. Compare it with the per-filter limit

    Check the value on every primary and replica, not only the node you are connected to.

    valkey-cli CONFIG GET bf.bloom-memory-usage-limit
  5. Validate a scaling filter's ceiling

    Use a scratch key, then delete it. Skip this step for NONSCALING.

    valkey-cli BF.INSERT tmp:check CAPACITY 1000000 \ ERROR 0.01 VALIDATESCALETO 50000000 valkey-cli DEL tmp:check
  6. Create the real filter explicitly

    Reserve it before the first write, so no client creates a default filter first.

    valkey-cli BF.RESERVE seen:events 0.01 1000000
  7. Watch growth

    Alert on sub-filter counts and on total Bloom memory in INFO BF.

    valkey-cli BF.INFO seen:events FILTERS valkey-cli INFO BF

Main risk: a client that calls BF.ADD before step 6 creates a 100-item default filter, and BF.RESERVE then fails with ERR item exists. Delete that key and reserve again before traffic grows.

How do large filters behave under replication and persistence?

Four behaviours in the 1.0.1 release notes and source matter once filters reach tens of megabytes.

  • Replication is deterministic. When a primary creates a filter, it replicates a BF.INSERT carrying the exact capacity, rate, tightening, expansion and seed, so the replica builds an identical bitmap. Adds that create nothing are replicated verbatim. Replicas skip the memory-limit check on replicated commands.
  • RDB loads do check the limit. The RDB loader recomputes each filter's size and refuses an object over the current bf.bloom-memory-usage-limit, logging Failed to restore bloom object: Object larger than the allowed memory limit. A replica or restore target with a lower limit than the primary can therefore fail its full sync or restore.
  • Snapshots carry the whole bitmap. RDB saves every sub-filter's bitmap, and an AOF rewrite emits one BF.LOAD per filter with the encoded object. Budget RDB, AOF and full-sync transfer size at roughly the filter's Size.
  • One filter is one key in one slot. In cluster mode, a 100 MB filter sits on one shard and moves as one key when its slot is migrated. Split by tenant or time window if you need it spread across shards.
bash
# On each node: confirm the module version, the limit, and Bloom memory
valkey-cli MODULE LIST
valkey-cli CONFIG GET bf.bloom-memory-usage-limit
valkey-cli INFO BF
valkey-cli MEMORY USAGE seen:events

Interpretation: MODULE LIST shows the module as bf, with version 10001 for 1.0.1. INFO BF reports bf_bloom_total_memory_bytes, bf_bloom_num_objects and bf_bloom_num_filters_across_objects, plus defrag hit and miss counters. A rising ratio of sub-filters to objects means filters are scaling out more than you planned.

Patch level

valkey-bloom 1.0.1, released in February 2026, fixes CVE-2026-21864 (GHSA-mc2g-h759-3qw2), a remote denial of service from a malformed RESTORE command. 1.0.0 is affected. valkey-bundle images 8.1.11, 9.0.7 and 9.1.4 all ship 1.0.1, per the bundle's versions.json.

Is valkey-bloom compatible with RedisBloom commands?

For the core commands, yes. The valkey-bloom README says it is API compatible with the Bloom filter command syntax of the Valkey client libraries and their Redis equivalents. The differences are at the edges.

Areavalkey-bloom 1.0.1RedisBloom
Core commandsBF.ADD, MADD, EXISTS, MEXISTS, CARD, RESERVE, INFO, INSERTSame names
Dump and loadBF.LOAD (used by AOF rewrite)BF.SCANDUMP and BF.LOADCHUNK
Other probabilistic typesNone shippedCuckoo, count-min sketch, top-k, t-digest
NONSCALING with EXPANSIONRejectedBoth listed in the syntax
BF.INFO extrasERROR, TIGHTENING, MAXSCALEDCAPACITYNot available
Data type namebloomfltrMBbloom--

Because the type names and hashing differ, filters move by re-inserting the source items, not by copying RDB files. The Redis Stack to valkey-bundle migration guide covers that cutover. For the wider server comparison, see Redis vs Valkey.

Which patterns suit a Bloom filter: deduplication or a cache-penetration guard?

A false positive means something different in each, and Bloom filters cannot delete items, so pick the rate and key layout to match.

Deduplication

BF.ADD is check-and-set in one command: it returns 1 if the item was new and 0 if it was probably seen. Use the return value directly. A separate BF.EXISTS followed by BF.ADD leaves a race between two workers.

bash
# One key per day, sized for the day's volume, expiring after a week
127.0.0.1:6379> BF.RESERVE dedup:2026-11-10 0.001 5000000 NONSCALING
OK
127.0.0.1:6379> EXPIRE dedup:2026-11-10 604800
(integer) 1
127.0.0.1:6379> BF.ADD dedup:2026-11-10 order:81234:email-sent
(integer) 1
127.0.0.1:6379> BF.ADD dedup:2026-11-10 order:81234:email-sent
(integer) 0

Interpretation: a 0 on a genuinely new item is a false positive, so that item is skipped. At 0.001, about one new item in a thousand is skipped once the day's filter is full. If a skipped notification or event is not acceptable, confirm a 0 against the source of truth before dropping the item. Time-windowed keys also give you deletion: the whole day expires together.

Cache-penetration guard

Requests for IDs that do not exist miss the cache every time and fall through to the database. A filter of every valid ID answers "definitely not" without a database read. The cache-aside and invalidation side of this design is covered in solving cache invalidation and stampede in Valkey.

python
import valkey

r = valkey.Valkey(host="10.0.0.5", port=6379)

def get_product(product_id: str):
    # 0 means the ID was never added: skip the cache and the database
    if r.execute_command("BF.EXISTS", "valid:products", product_id) == 0:
        return None
    cached = r.get(f"product:{product_id}")
    if cached is not None:
        return cached
    return load_from_db_and_cache(product_id)   # your existing path

def create_product(product_id: str, row):
    insert_into_db(row)
    r.execute_command("BF.ADD", "valid:products", product_id)

Interpretation: every write path that creates an ID must also add it to the filter, or new rows will look absent. Deleted IDs stay in the filter as permanent "maybe" answers, and they pass through to the database as before. Rebuild the filter on a schedule under a new key, then switch readers with RENAME. A guard sees mostly misses, which check every sub-filter, so reserve it as NONSCALING or with a large starting capacity.

Frequently asked questions

What is the maximum size of a Bloom filter in Valkey?

By default, 128 MB per filter. valkey-bloom's bf.bloom-memory-usage-limit setting defaults to 134,217,728 bytes, and any create or scale-out that would exceed it fails with "ERR operation exceeds bloom object memory limit". You can raise it with CONFIG SET or in valkey.conf. Keep the same value on every node, because RDB loads enforce it too.

How many items fit in a default Valkey Bloom filter?

A filter created by BF.ADD starts at 100 items and doubles each time it fills. Under the 128 MB limit, it reaches 26,214,300 items in 18 sub-filters and about 102 MiB. A non-scaling filter at the same 1% rate holds about 112 million items under the same limit.

What does VALIDATESCALETO do in BF.INSERT?

It rejects the command if a scaling filter built from the given capacity, error rate and expansion could never hold the requested number of items. The failure can come from the memory limit or from the error rate degrading to zero. Nothing is created on failure. It cannot be combined with NONSCALING, and it checks the command's arguments, not an existing key.

Does a scaling Bloom filter keep the false-positive rate I set?

Not exactly. Each new sub-filter gets half the previous rate under the default 0.5 tightening ratio. A lookup can still match any of them, so once they fill, the combined rate approaches the sum of their rates. That sum stays under twice the rate you set. BF.INFO keeps reporting the original rate.

Can I move RedisBloom filters to valkey-bloom?

The commands carry over, but the data does not. RedisBloom stores filters as MBbloom-- and valkey-bloom as bloomfltr, with different hashing, so RDB files and SCANDUMP chunks cannot be loaded. Recreate each filter with BF.RESERVE and re-insert the source items from your database or event log.

Key takeaways

  • Size before you create: bytes are about n × −ln(p) ÷ 3.844, which is 1.2 MB per million items at 1% and 1.8 MB at 0.1%.
  • The per-filter cap is bf.bloom-memory-usage-limit, 128 MB by default. It is checked on every create and scale-out, and on RDB load, so set it the same on every node.
  • Default filters from BF.ADD stop at 26,214,300 items, use about 102 MiB and check up to 279 hash positions per miss. Reserve explicitly instead.
  • Use NONSCALING when the count is known, and BF.INSERT ... VALIDATESCALETO or BF.INFO ... MAXSCALEDCAPACITY when it is not.
  • Run valkey-bloom 1.0.1, and plan deletes with time-windowed keys or scheduled rebuilds, because filters cannot remove items.

Size and tune Valkey Bloom filters with JusDB

JusDB's Valkey performance tuning team can review your Bloom filter keys against their real growth. That covers capacity, error rate, sub-filter counts and the per-filter memory limit on every node. We can then help plan resized filters and the rebuild or cutover to move traffic onto them.

Bring the output of INFO BF, BF.INFO for your largest filters, and your expected item counts. Your team approves every production change.

Share this article

Database engineering notes

Articles like this one, in your inbox. No spam, unsubscribe anytime.

JusDB Team

Official JusDB content team

Keep reading

Moving a Multi-Database Valkey Instance into a 9.x Cluster

Move a Valkey instance that uses SELECT 1 to 15 into a 9.x cluster: keep or remap databases, copy each one, verify counts per database, and keep a way back.

Redis18 minNov 10, 2026
Read

Valkey Keyspace Notifications in Production: Expired Events, hexpired and Cluster Mode

Run Valkey keyspace notifications in production: why expired and hexpired events lag the TTL, how to subscribe on every cluster node, and when a stream is safer.

Redis20 minNov 10, 2026
Read

Valkey GLIDE in Production: AZ-Affinity Reads and Migrating from Legacy Clients

Configure Valkey GLIDE AZ-affinity reads on servers and clients, learn what GLIDE 2.5.3 does not support, and migrate from redis-py, Jedis, ioredis, or go-redis one service at a time.

Redis20 minNov 10, 2026
Read