Redis Error Guide: High mem_fragmentation_ratio — RSS Far Exceeds used_memory
Fix high Redis mem_fragmentation_ratio and RSS >> used_memory: diagnose allocator fragmentation, activedefrag, jemalloc, swap, and churn via INFO memory.
- #redis
- #troubleshooting
- #errors
- #memory
Overview
mem_fragmentation_ratio in INFO memory is the ratio of the memory the operating system has given Redis (used_memory_rss, the resident set size) to the memory Redis actually asked its allocator for (used_memory). A ratio slightly above 1.0 is normal and healthy. A ratio well above 1.0 (say 1.5+) means the process’s RSS is much larger than the live dataset — memory is fragmented: the allocator holds pages that are only partially used and cannot return them to the OS. The danger is that RSS, not used_memory, is what the OS and the OOM killer see, so a fragmented instance can be OOM-killed or forced into swap even though its logical data is small.
Representative INFO memory output showing the problem:
used_memory:2147483648 # ~2.0 GiB of live data
used_memory_human:2.00G
used_memory_rss:3865470566 # ~3.6 GiB resident
used_memory_rss_human:3.60G
mem_fragmentation_ratio:1.80 # RSS is 1.8x the dataset
mem_allocator:jemalloc-5.3.0
Note the inverse case: a ratio below 1.0 means part of Redis has been swapped to disk — also bad, and worth catching, since swap causes severe latency.
Symptoms
mem_fragmentation_ratiopersistently above ~1.5 whileused_memoryis stable.used_memory_rssfar exceedsused_memory; host memory pressure despite a modest dataset.- OOM-kills or swap activity even though logical data fits in RAM.
- Fragmentation grows over time on workloads with heavy churn (variable-size values, frequent delete/rewrite).
redis-cli INFO memory | grep -E 'used_memory:|used_memory_rss:|mem_fragmentation_ratio|mem_allocator'
mem_fragmentation_ratio:1.80
mem_allocator:jemalloc-5.3.0
Common Root Causes
1. Allocator fragmentation from variable-size churn
Workloads that constantly write, resize, and delete values of differing sizes leave the allocator’s size-class bins with holes it cannot reclaim — the classic external fragmentation pattern.
redis-cli MEMORY STATS | grep -E 'fragmentation|allocator_frag|allocator_rss'
redis-cli MEMORY DOCTOR
Sam, I detected a few issues in this Redis instance memory implants:
* High allocator fragmentation: this instance has an allocator ...
2. Active defragmentation disabled
jemalloc can defragment in place, but only if activedefrag is on. Left off, fragmentation is never actively reclaimed.
redis-cli CONFIG GET activedefrag
redis-cli CONFIG GET maxmemory
activedefrag no
3. Ratio below 1.0 — Redis is swapping
If the ratio is < 1.0, part of Redis’s memory is in swap, so RSS undercounts logical memory. This is a different, more urgent problem.
grep VmSwap /proc/$(pgrep -o redis-server)/status
redis-cli INFO memory | grep mem_fragmentation_ratio
VmSwap: 524288 kB # Redis is swapping — ratio < 1.0
4. Peak memory much higher than current (transient spike aftermath)
A past spike (used_memory_peak) grew RSS; after data shrank, the allocator kept the pages, inflating the ratio.
redis-cli INFO memory | grep -E 'used_memory_peak|used_memory_peak_perc'
Diagnostic Workflow
Step 1: Read the ratio and the raw numbers
redis-cli INFO memory | grep -E 'used_memory:|used_memory_rss:|used_memory_peak|mem_fragmentation_ratio|mem_allocator'
Confirm the ratio is genuinely high (RSS >> used_memory) and note the allocator — active defrag only works with jemalloc.
Step 2: Ask Redis’s memory doctor
redis-cli MEMORY DOCTOR
redis-cli MEMORY STATS | grep -E 'allocator_frag_ratio|allocator_rss_ratio|frag'
MEMORY DOCTOR explicitly flags high fragmentation and whether the sample is large enough to trust.
Step 3: Rule out swap (ratio < 1.0)
grep VmSwap /proc/$(pgrep -o redis-server)/status
free -h
cat /proc/sys/vm/overcommit_memory # want 1 for Redis
If Redis is swapping, fix memory sizing/overcommit first — that dominates.
Step 4: Check defrag config and thresholds
redis-cli CONFIG GET activedefrag
redis-cli CONFIG GET active-defrag-ignore-bytes
redis-cli CONFIG GET active-defrag-threshold-lower
redis-cli CONFIG GET active-defrag-threshold-upper
Example Root Cause Analysis
A cache instance holding ~2 GiB of live data was using ~3.6 GiB RSS and triggering host memory alerts.
redis-cli INFO memory | grep -E 'used_memory:|used_memory_rss:|mem_fragmentation_ratio'
used_memory:2147483648
used_memory_rss:3865470566
mem_fragmentation_ratio:1.80
MEMORY DOCTOR confirmed high allocator fragmentation, and VmSwap was 0 (so not a swap/ratio-<1 case). The workload churned session objects of widely varying sizes with frequent expiry — a textbook external-fragmentation pattern. activedefrag was off.
Fix: enable jemalloc active defragmentation with sensible thresholds so Redis reclaims fragmented pages online without a restart:
redis-cli CONFIG SET activedefrag yes
redis-cli CONFIG SET active-defrag-ignore-bytes 100mb
redis-cli CONFIG SET active-defrag-threshold-lower 10
redis-cli CONFIG SET active-defrag-threshold-upper 100
# persist the same directives to redis.conf
Over the next hour, active defrag walked the keyspace and RSS fell toward the live dataset size:
redis-cli INFO memory | grep mem_fragmentation_ratio
mem_fragmentation_ratio:1.18
The host memory alert cleared. Because defrag consumes some CPU, the thresholds were tuned so it engages only when fragmentation is meaningful.
Prevention Best Practices
- Enable
activedefrag yes(with jemalloc) on churny workloads, and tuneactive-defrag-threshold-lower/upperandactive-defrag-ignore-bytesso it runs only when worthwhile. - Confirm
mem_allocatoris jemalloc — active defrag does not work with libc malloc. - Keep the dataset well under host RAM and set
vm.overcommit_memory=1so Redis never swaps (which drives the ratio below 1.0). - Set
maxmemoryplus an eviction policy so transient spikes cannot inflate RSS unbounded. - Reduce churn where possible: prefer stable value sizes and appropriate data structures; avoid constant large delete/rewrite cycles.
- Monitor
mem_fragmentation_ratio,used_memory_rss, andVmSwap; alert on ratio >1.5 or <1.0. See more Redis error guides.
Quick Command Reference
# The core numbers
redis-cli INFO memory | grep -E 'used_memory:|used_memory_rss:|used_memory_peak|mem_fragmentation_ratio|mem_allocator'
# Redis memory advisor
redis-cli MEMORY DOCTOR
redis-cli MEMORY STATS | grep -iE 'frag'
# Rule out swap (ratio < 1.0)
grep VmSwap /proc/$(pgrep -o redis-server)/status
free -h
# Enable & tune active defrag (jemalloc only)
redis-cli CONFIG GET activedefrag
redis-cli CONFIG SET activedefrag yes
redis-cli CONFIG SET active-defrag-threshold-lower 10
redis-cli CONFIG SET active-defrag-ignore-bytes 100mb
Conclusion
A high mem_fragmentation_ratio means Redis’s resident memory (RSS) far exceeds the live dataset (used_memory) — fragmented pages the allocator holds but cannot return. Because the OS and OOM killer act on RSS, this can get an instance killed or swapped despite small logical data. The causes:
- Allocator fragmentation from variable-size, high-churn workloads.
activedefragdisabled, so fragmentation is never reclaimed.- A ratio below 1.0 — Redis is swapping, a distinct and urgent problem.
- A past memory peak leaving inflated RSS after data shrank.
Read INFO memory and MEMORY DOCTOR, rule out swap via VmSwap, then enable and tune jemalloc activedefrag to reclaim pages online. Keep the dataset off swap and under a sane maxmemory so fragmentation stays bounded.
Download the Free 500-Prompt DevOps AI Toolkit
500 battle-tested, copy-paste AI prompts engineered by a senior systems engineer — every one with fill-in placeholders and safety/back-out notes. Drop your email and it's yours.
- 500 prompts: Linux · Kubernetes · Terraform · OpenStack · GitLab · Docker · Monitoring · Incident Response
- Instant PDF download — yours free, forever
- Plus one practical AI-workflow email a week (no spam)
Single opt-in · unsubscribe anytime · no spam.