← Blog
Terracotta pebbles occupy part of a sage ceramic tray, with spare space under an ivory arch and a blue pebble in a scoop outside.
Published on
2026-11-10

Redis memory and eviction: set maxmemory for the workload

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.

Separate expiration, eviction, and an out-of-memory kill

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.

Choose a Redis eviction policy for the data

  • noeviction: Redis rejects commands that require more memory instead of evicting keys. Reads can continue. The application must handle rejected writes.
  • allkeys-lru: candidates come from all keys, favoring removal of less recently used entries. A reasonable cache policy to evaluate when recent access predicts reuse.
  • allkeys-lfu: favors retaining frequently accessed entries. Compare it with LRU using your actual access distribution.
  • volatile policies: consider only keys with an expiration. If there are no eligible keys, memory-growing writes can fail.

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.

Keep cache and queue requirements separate

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.

Budget headroom before setting maxmemory

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:

AllowanceMiB
VM total4096
Host and operating-system allowance1024
Other application allowance1024
Unallocated host margin512
Remaining Redis container allowance1536
Headroom inside that container allowance512
Candidate maxmemory after that headroom1024

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}

Express the two limits without overwriting the existing lab

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.

Inspect actual memory and effective settings

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.

Test pressure with bounded, disposable inputs

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.

  1. On an isolated cache instance, run a representative mix of reads and writes. Record misses, application latency, source-database load, and eviction-counter changes. Confirm that missing values are rebuilt correctly.
  2. For a separate noeviction evaluation, check the application’s response to rejected writes. A visible error handled correctly is different evidence from a process crash or silent loss.
  3. If evaluating a volatile policy, include keys with and without TTLs. Confirm the application tolerates the case where no eligible keys remain.
  4. Repeat with representative persistence activity and connection counts. Measure peak process and container memory instead of treating an idle PING as a capacity test.

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.

Use the result to choose the next change

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.

Your next workload belongs on Hivenet.

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.