You check INFO memory and used memory keeps climbing. You check your key count and it's flat, or even shrinking. This is one of the most disorienting failure patterns in Redis operations — the math doesn't add up, and teams often spend days chasing the wrong culprit before finding the real one.
This post walks through the diagnosis and fix based on a real multi-week production investigation, including the exact commands and thresholds that mattered.
If key count is flat, why is memory still growing?
In the overwhelming majority of cases, the answer is: it's not your keys, it's your index.
If you're running RediSearch (the full-text/secondary-index module) or any similar indexing module, the index itself consumes memory independently of your primary keyspace. An index that grows unboundedly — often because it's being rebuilt or updated far more frequently than intended — can climb toward your maxmemory limit while DBSIZE shows nothing unusual.
This was diagnosed directly in a multi-session Redis assessment: the team confirmed a memory leak was linked to the Redis full-text indexing plugin, with memory usage rising toward 60% and triggering crashes during re-indexing operations. Justin Clark and Eugene Abovsky identified it as a software bug in the indexing module — not a hardware or configuration issue, and not something happening in the primary keyspace at all.
First diagnostic step: run FT.INFO <index_name> on each of your search indexes and look at the index memory footprint reported. Compare that against your total used_memory from INFO memory. If the index accounts for a disproportionate and growing share, you've found your leak source — not in the data, but in the index structure sitting on top of it.
What specifically causes an index to leak memory like this?
The most common root cause is excessive reindexing driven by high-frequency, low-value updates.
In one production investigation, the team traced the leak to device heartbeat updates — every heartbeat triggered a full reindex of the associated document, even when the actual change was trivial. Each of those reindex operations left behind memory that wasn't being reclaimed, and because heartbeats fired constantly, the leak compounded over hours until the instance crashed.
A second contributing factor identified in the same investigation: indexing fields that don't need to be indexed, such as UUID fields. Indexing a high-cardinality field like a UUID inflates the index memory footprint substantially for very little query benefit, since UUIDs are rarely the target of range queries or fuzzy search.
Diagnostic questions to ask your own deployment:
- What fields are actually being indexed, and do queries actually use all of them?
- What triggers a document update — is it a meaningful state change, or a high-frequency signal like a heartbeat or timestamp tick?
- Is there a scheduled reindex job running, and is it actually completing and freeing memory, or silently failing?
What's the fastest way to stabilize a Redis instance that's leaking memory right now?
If you're in an active incident — memory climbing toward your limit and a crash imminent — there's a proven stopgap: drop and rebuild the affected index.
This doesn't fix the root cause, but it reliably reclaims the leaked memory as an immediate mitigation. In one incident, dropping and rebuilding the index reduced memory usage from 50% down to 36% of the configured maximum — enough headroom to stabilize the system while the underlying fix was developed.
The stopgap procedure:
- Confirm which index is growing disproportionately via
FT.INFO - Schedule the drop/rebuild for a low-traffic window if possible — rebuilding a large index is not instantaneous and briefly affects query availability
FT.DROPINDEX <index_name>(withoutDDif you want to preserve the underlying hash/JSON data, since you only want to remove the index structure, not your keys)- Recreate the index with
FT.CREATE - Monitor
FT.INFOandINFO memoryafterward to confirm the reclaim held
For production environments where this keeps recurring, this can be automated as a scheduled job — but treat it as a mitigation, not a fix. Automating a workaround without addressing the reindex trigger just moves the crash window further out.
What configuration changes actually prevent the crash?
Beyond fixing the reindex trigger itself, two configuration-level changes reduce blast radius while the underlying fix is developed:
Set an explicit maxmemory with an appropriate eviction policy. In one incident, the team implemented a new max memory setting alongside an allkeys-lru eviction policy specifically to protect system stability for critical customers — trading some cache-hit-rate degradation for the guarantee that the instance won't hard-crash from memory exhaustion. This is a deliberate stability-over-performance tradeoff during an active leak investigation, not necessarily a permanent posture.
Tune garbage collection behavior where applicable. In module-heavy Redis deployments, aggressive GC tuning was tested specifically to improve memory retention behavior — worth investigating if your module vendor exposes GC-related configuration.
Separate high-frequency, low-value data from indexed keys. The most durable fix identified in the underlying investigation was architectural: separate volatile heartbeat-style data from the indexed keys entirely, so routine status pings don't trigger reindexing at all. If your application pattern involves frequent updates to a small subset of fields on an otherwise-stable document, consider storing the volatile fields in a separate, non-indexed key.
Should I upgrade my Redis version to fix this?
Possibly — but validate the specific bug first. In the investigation referenced throughout this post, part of the diagnostic process included reviewing whether the memory leak was a known, patched issue in later Redis versions, since the affected environment was running an older release. Independent code analysis of the search module's source was used to identify whether known patch versions addressed the specific leak pattern observed.
Before committing to an upgrade as your fix, confirm:
- Whether the specific module version you're running has a documented memory leak fix in a later release
- Whether the leak is actually in the module itself, or in your indexing pattern (an upgrade won't fix a UUID-indexing problem)
- Whether you have a tested rollback plan, since Redis version upgrades in production require the same care as any stateful service upgrade
Is this a reason to consider migrating to Valkey?
It's worth evaluating as part of a broader remediation plan, particularly if you're also weighing licensing considerations. Some teams facing exactly this kind of module-related instability have used the investigation as an opportunity to test Valkey compatibility in parallel — validating whether their existing client code and indexing patterns behave identically on Valkey before committing either direction. We cover that decision in more depth separately.
What should ongoing monitoring look like after you've stabilized?
Once you've addressed the immediate crash risk, put permanent monitoring in place so this doesn't silently recur:
- Track index memory as a distinct metric, not just total
used_memory. A dashboard panel showingFT.INFOmemory alongside total memory makes the next leak visible early instead of at 60% utilization. - Alert on reindex job frequency and duration. If your reindex cadence changes unexpectedly — more frequent, or silently failing to complete — that's your early warning.
- Verify your maxmemory eviction policy matches your actual tolerance for data loss.
allkeys-lruprotects stability but will evict data under pressure; if that's not acceptable for your use case, the real fix has to be the reindex trigger, not the eviction policy.
Get Help With Redis Memory Leaks and Index Growth
Seeing Redis memory climb independent of your key count? That's a pattern we trace to its actual source — index growth, reindex triggers, and module bugs that generic infrastructure tuning won't catch. AceMQ provides enterprise Redis support for production estates. Talk to an AceMQ engineer.