
A Redis eviction policy decides what happens when memory pressure reaches the configured limit. A cache may discard a value and rebuild it. A queue cannot treat a pending job as a disposable cache entry. Choose that behavior before choosing a VM size, then leave room for the Redis process and the rest of the host.
This guide covers policy selection, a hypothetical memory budget, and checks to perform before accepting a configuration. It builds on our Redis hosting decision guide and private Redis Docker Compose setup; it does not replace their networking, credentials, or persistence instructions.
Validation, November 10, 2026: Python checks cover the budget arithmetic and invalid inputs. Docker Compose 5.1.4 checks cover merging the memory override with a separate copy of the existing lab, the declared memory cap, project isolation, and retained network and volume settings. Redis configuration fragments were compared with the documented directive names and policy values. The Docker Linux engine was unavailable. No Redis server, eviction, out-of-memory behavior, workload, restart, recovery, or Hivenet deployment was tested. Numerical allowances below are invented planning inputs, not measurements or recommendations.
Expiration removes a key when its time-to-live runs out. Eviction selects keys under a memory policy and can remove a key before its TTL ends. A container or host out-of-memory kill is a separate operating-system event that can stop Redis. A TTL therefore does not promise that a cached value will remain available for that duration. See the EXPIRE reference for expiration semantics.
A Redis limit and a container limit serve different purposes. maxmemory controls the accounting used for eviction decisions; it is not a hard ceiling on every byte used by the process. The container boundary constrains the wider process environment, while the VM must also support its operating system and other services. Docker describes the consequences of exhausting memory in its resource-constraint guidance.
If the application reports a memory error, first identify which boundary failed. An OOM response from Redis, a killed container, a connection timeout, and a cache miss call for different investigations. Increasing a timeout will not fix a container that cannot stay within its memory allowance.
LRU and LFU use approximations, so a small demonstration should not assert the identity of the next evicted key. The current policy list also includes random selection and volatile-ttl, which favors keys with the shortest remaining TTL. Use the official eviction guide to check the full list for your version.
Redis 8.10 configuration also lists allkeys-lrm and volatile-lrm: least recently modified policies whose timestamps change on writes rather than reads. They answer a different question from recent access. Do not assume an older server supports them. The versioned configuration reference is the source for these names; this article does not test them.
For a rebuildable cache, decide what happens on a miss: fetch from the source, return a bounded error, or serve an explicitly permitted stale value. Also bound the requests that can reach the source during a cold start. A high cache hit rate is useful only when misses remain correct and affordable.
For a broker, silently discarding keys can break work delivery. Celery documents failures caused by Redis key eviction. Evaluate noeviction with explicit handling for publish failures, queue growth, retries, and admission control. It prevents policy-driven eviction; it does not guarantee successful writes or durable jobs. Our Celery with Redis guide keeps those delivery concerns separate.
Use separate Redis instances when cache and queue policies conflict. Choosing database 0 for one and database 1 for the other only separates key namespaces within the same server. It does not create independent memory limits, eviction policies, or failure boundaries. The SELECT reference explains Redis logical databases. Separate instances on one VM still share host resources and host failure risk.
Measure representative data rather than multiplying serialized payload size by key count. Keys, values, object encodings, and bookkeeping consume memory. MEMORY USAGE estimates the allocation for an individual key, including its overhead; sampling and data structure affect that estimate. It does not estimate the entire process. Redis’s memory optimization guide explains why representation and object size matter.
A useful planning order is: reserve host capacity, account for other applications, keep unallocated margin, then divide the Redis container allowance between a candidate maxmemory and additional headroom. Do not count the same reserve twice. The extra allowance must be challenged with observed process memory, client buffers, fragmentation, and persistence or replication activity. There is no universal safe percentage in this guide.
Here is a hypothetical 4 GiB host budget, expressed in MiB. These are arithmetic inputs selected to make the boundaries visible:
| Allowance | MiB |
|---|---|
| VM total | 4096 |
| Host and operating-system allowance | 1024 |
| Other application allowance | 1024 |
| Unallocated host margin | 512 |
| Remaining Redis container allowance | 1536 |
| Headroom inside that container allowance | 512 |
| Candidate maxmemory after that headroom | 1024 |
The last two rows divide the container allowance; they are not additional host allocations. A 1024 MiB candidate does not mean you can store 1024 MiB of application payload, and 512 MiB of headroom has not been demonstrated sufficient. A workload with larger transient demands would invalidate this example even though its arithmetic balances.
Save this optional arithmetic helper as budget.py. It reads no machine information and makes no Redis connection:
"""Illustrative arithmetic only. Does not inspect or size a Redis deployment."""
import json
def budget(vm_mib, host_mib, other_apps_mib, spare_mib, redis_headroom_mib):
values = (vm_mib, host_mib, other_apps_mib, spare_mib, redis_headroom_mib)
if any(type(value) is not int or value < 0 for value in values):
raise ValueError("Use nonnegative integer MiB values.")
container = vm_mib - host_mib - other_apps_mib - spare_mib
candidate = container - redis_headroom_mib
if vm_mib == 0 or container <= 0 or candidate <= 0:
raise ValueError("The allowances leave no positive Redis memory budget.")
return {"container_mib": container, "candidate_maxmemory_mib": candidate}
if __name__ == "__main__":
print(json.dumps(budget(4096, 1024, 1024, 512, 512), sort_keys=True))
python3 budget.py
The locally verified output for those hypothetical inputs is:
{"candidate_maxmemory_mib": 1024, "container_mib": 1536}
For configuration review, use a new directory with a copy of the four files from the Redis Compose guide. Do not copy its secrets directory or attach its existing volume. Use a fresh project name, redis-memory-lab, and stop if that name or its volumes already exist. Generate credentials in the new directory using the existing helper before validating the Compose files.
Save this hypothetical container override as compose.memory.yaml. It only changes the Redis service memory cap:
services:
redis:
mem_limit: 1536m
In the copied redis.conf, replace the existing maxmemory and maxmemory-policy lines with the following pair for a no-eviction evaluation. Preserve every other directive. This is a fragment, not a complete Redis configuration:
maxmemory 1024mb
maxmemory-policy noeviction
For a separate disposable cache evaluation, select allkeys-lru or allkeys-lfu instead of noeviction. Change only one policy at a time. Do not apply a cache policy to a queue or reuse production data to force the limit. The selected Redis tag in the existing lab remains unchanged; this article adds no image validation.
docker compose -p redis-memory-lab -f compose.yaml -f compose.memory.yaml config --quiet
docker compose -p redis-memory-lab -f compose.yaml -f compose.memory.yaml --profile tools config --quiet
These commands parse Compose configuration. They do not parse the mounted Redis configuration file or prove that the kernel will enforce the limit. In our local check, 1536m resolves to 1,610,612,736 bytes; Redis documents 1024mb as 1,073,741,824 bytes. Use consistent units when comparing them. The Compose mem_limit reference defines the container setting.
Do not start this example unless the actual host can accommodate the proposed allowances. When you do test it, use the same project name and both Compose files for every lifecycle command. Startup, authentication, enforcement, and policy behavior remain unexecuted here. Raising the declared limit is not proof that a VM has spare memory.
The following Redis commands are an operator checklist for an already authenticated, authorized session. They omit connection details deliberately: use your established private route and credential handling. Do not expose port 6379 or put a password in shared command history to make diagnostics easier.
INFO server
INFO memory
INFO stats
INFO persistence
CONFIG GET maxmemory maxmemory-policy
The restricted app user from the Compose guide is not granted INFO or CONFIG. Do not run these through its client wrapper and mistake an authorization error for missing memory data. Arrange appropriately scoped operator access or use the service’s supported diagnostics. CONFIG GET reports effective settings; this checklist does not issue CONFIG SET or alter a running server.
From INFO, compare used_memory, used_memory_rss, maxmemory, and mem_not_counted_for_evict. The last field reports memory excluded from eviction accounting, including transient replication and AOF buffers. Inspect evicted_keys, expired_keys, and lookup hits/misses over the same observation window. Check the server identity and uptime so restarts or resets do not produce misleading counter differences.
Do not add every reported memory field together: several describe overlapping allocations. A large RSS value also does not prove that all of it is live key data. Compare Redis observations with the container’s actual memory use, host availability, and application latency. Persistence work and operating-system paging can change the picture; the Redis latency guidance covers those effects.
Before testing, record the image digest, effective policy, memory limits, key-size distribution, TTL rules, and a fixed workload budget. Set a maximum duration, request count, data volume, and acceptable host pressure. Stop when any bound is reached. Reaching a bound without eviction is an inconclusive pressure test, not a reason to keep filling memory indefinitely.
These are proposed checks, not captured results. Do not promise that a particular key survives LRU/LFU, infer production throughput from synthetic keys, or claim queue recovery from a memory test. Use the Redis persistence and recovery guide for the separate restart, backup, and isolated-restore questions.
If a cache is evicting heavily but misses are cheap and latency is acceptable, a larger VM may not help enough to justify it. If misses overload the source, compare retention rules, object representation, and a larger measured working-set allowance. If a queue grows, investigate arrival rate, worker capacity, and backpressure before increasing a limit that only postpones the next failure.
Return to the CPU VM buying guide with measured memory, CPU, storage, and recovery needs. More vCPUs do not automatically solve a memory constraint. Hivenet’s CPU VM documentation supplies the product context; no Hivenet memory capacity, availability, benchmark, or deployment result is established by this article.
Pick one AI, compute, or storage workload and see the difference for yourself. Spin it up in minutes, or let our team map your fastest path to production.