Troubleshooting Redis OOM: ‘command not allowed when used memory limit reached’ on macOS
Resolve the Redis Out-Of-Memory error on your macOS local development environment by adjusting memory limits, eviction policies, and optimizing Redis usage.
Resolve the Redis Out-Of-Memory error on your macOS local development environment by adjusting memory limits, eviction policies, and optimizing Redis usage.
When developing locally on macOS, encountering the "Redis OOM command not allowed when used memory limit reached" error can be a frustrating roadblock. This message indicates that your Redis instance has hit its configured maxmemory limit and, by default, is refusing further write operations to prevent uncontrolled memory consumption and potential system instability. While alarming, this is Redis's self-preservation mechanism at play, and it's a common issue in local development environments where Redis might be running with default or low resource allocations. This guide will walk you through diagnosing and resolving this memory constraint.
Symptom & Error Signature
When this error occurs, your applications will fail to store or modify data in Redis, manifesting as various errors in your application logs or terminal output.
Typical Application Error Output (Example – PHP/Node.js/Python clients):
RedisException: OOM command not allowed when used memory > 'maxmemory' in /path/to/your/app/vendor/predis/predis/src/Client.php:382
Error: Redis command failed: OOM command not allowed when used memory > 'maxmemory'
at Commander._sendCommands (/path/to/node_modules/ioredis/lib/commander.js:235:25)
at Redis.set (/path/to/node_modules/ioredis/lib/redis/index.js:636:25)
...
Redis CLI Output:
Attempting to execute any write command (like SET, LPUSH, HSET) directly via redis-cli will produce:
127.0.0.1:6379> SET mykey "somevalue"
(error) OOM command not allowed when used memory > 'maxmemory'
Root Cause Analysis
The "OOM command not allowed" error is a direct consequence of your Redis instance reaching its maxmemory configuration limit. Here's a breakdown of the underlying reasons:
maxmemoryLimit Reached: Redis has a configurablemaxmemorydirective that dictates the maximum amount of RAM it is allowed to consume. When Redis's used memory (including data and internal overhead) exceeds this limit, it enters a protective state.noevictionPolicy (Default): By default, whenmaxmemoryis reached, Redis'smaxmemory-policyis often set tonoeviction. This policy ensures that no data is automatically removed from the dataset. While preserving data integrity, it comes at the cost of blocking all write commands to prevent further memory allocation.- Insufficient Resource Allocation:
- Homebrew Redis: On macOS, a Homebrew-installed Redis might not have an explicit
maxmemoryset by default, or it could be set to a conservative value. If nomaxmemoryis set, Redis will try to use all available system memory, which can lead to macOS-level OOM issues. However, if this specific errorused memory > 'maxmemory'occurs, it meansmaxmemoryis configured. - Docker Desktop: If Redis is running inside a Docker container, the container itself (and thus Redis) is constrained by the memory limits set for the Docker Desktop VM. If the
maxmemorywithin Redis is set to a high value, but the Docker VM doesn't have enough RAM, Redis might still hit its internal limit before the OS-level OOM occurs, or the Docker process itself might be killed.
- Homebrew Redis: On macOS, a Homebrew-installed Redis might not have an explicit
- Application Inefficiency / Data Bloat:
- Large Dataset: Your local development environment might be running with a larger-than-expected dataset, or you might be testing with bulk data imports.
- Unoptimized Key Management: Storing large objects, not setting Time-To-Live (TTL) for transient data, or using inefficient data structures can quickly consume memory.
- Memory Leaks: Application logic might be inadvertently creating and storing an excessive number of keys or very large keys without proper cleanup.
Step-by-Step Resolution
Follow these steps to diagnose and resolve the Redis OOM issue on your macOS local environment.
1. Verify Current Redis Memory Usage and Configuration
First, let's ascertain how much memory Redis is using and what its current maxmemory limit is.
Connect to Redis CLI:
redis-cliCheck Current Memory Usage:
127.0.0.1:6379> INFO memoryLook for lines like
used_memory_humanandused_memory_peak_humanto understand current and peak usage.Check
maxmemoryConfiguration:127.0.0.1:6379> CONFIG GET maxmemoryThis will show you the current
maxmemorylimit (in bytes). If it returns0, it means there's no explicit limit set within Redis itself, and it will try to use all available system memory. However, for the "OOM command not allowed" error to appear,maxmemorymust be set to a non-zero value.127.0.0.1:6379> CONFIG GET maxmemory-policyThis will confirm your current eviction policy, which is likely
noeviction.
2. Adjust Redis maxmemory Limit
You can increase the maxmemory limit either by modifying the redis.conf file or by configuring your Docker container. Choose the method relevant to your Redis setup.
Indiscriminately increasing
maxmemoryis not a solution for application-level memory leaks or inefficient Redis usage. It merely postpones the problem and can lead to system instability if Redis consumes too much RAM. Use this as a temporary measure or when genuinely more capacity is needed.
A. For Homebrew Redis on macOS
Locate
redis.conf: Theredis.conffile is typically located in:- For Apple Silicon (M1/M2/M3 Macs):
/opt/homebrew/etc/redis.conf - For Intel Macs:
/usr/local/etc/redis.conf
You can confirm its location using
brew info redis:brew info redisLook for the "Conf files" or "Configuration file" path.
- For Apple Silicon (M1/M2/M3 Macs):
Edit
redis.conf: Open the file with your preferred text editor (e.g.,nano,vim,code):nano /opt/homebrew/etc/redis.confSearch for
maxmemory. If it's commented out (# maxmemory <bytes>), uncomment it and set a suitable value. If it's already there, modify it. For a local development environment, starting with128mbor256mbis often sufficient, but you can go higher if your application genuinely needs it.# Example: Set maxmemory to 256 megabytes maxmemory 256mbYou can use
gbfor gigabytes as well (e.g.,1gb).Restart Redis Service: For the changes to take effect, you must restart Redis.
brew services restart redis
B. For Docker Container Redis
If you are running Redis in a Docker container (e.g., via docker-compose or docker run), you have a few options:
Option 1: Define
maxmemoryindocker-compose.yml(Recommended for local dev)Edit your
docker-compose.ymlfile to pass Redis configuration directly:version: '3.8' services: redis: image: redis:7.2-alpine # Or your preferred Redis version command: redis-server --maxmemory 256mb --appendonly yes # Add maxmemory here ports: - "6379:6379" volumes: - redis_data:/data # Optional: for persistence volumes: redis_data:Adjust
256mbto your desired limit. The--appendonly yesis included as a common good practice for persistence in development.Option 2: Mount a Custom
redis.confCreate a custom
redis.conffile in your project directory (e.g.,./redis-conf/redis.conf):# ./redis-conf/redis.conf maxmemory 256mb maxmemory-policy allkeys-lru # Or your desired policy appendonly yes # Add other Redis configurations as neededThen, modify your
docker-compose.ymlto mount this configuration:version: '3.8' services: redis: image: redis:7.2-alpine command: redis-server /usr/local/etc/redis/redis.conf # Point to the mounted conf ports: - "6379:6379" volumes: - ./redis-conf/redis.conf:/usr/local/etc/redis/redis.conf # Mount your custom conf - redis_data:/data volumes: redis_data:Restart Docker Container(s):
docker-compose down docker-compose up -dIf running Redis in Docker, ensure Docker Desktop itself has sufficient memory allocated to its VM. Go to Docker Desktop preferences -> Resources -> Memory and increase it if needed (e.g., to 4GB or 8GB).
3. Choose an Appropriate maxmemory-policy
The maxmemory-policy determines how Redis behaves when maxmemory is reached. The default noeviction policy blocks writes, which is what caused your error. For development, you might prefer a policy that automatically evicts older data to allow new data in.
Changing the
maxmemory-policyaway fromnoevictionmeans Redis will automatically delete keys when the memory limit is reached. This is acceptable for caches or transient data but can lead to data loss if your application relies on all data being persistently available in Redis.
Edit your redis.conf file (or docker-compose.yml command) and set one of the following policies:
maxmemory-policy noeviction: (Default) Refuses all write operations with an error. Best for ensuring no data loss.maxmemory-policy allkeys-lru: Evicts keys using a Least Recently Used (LRU) algorithm among all keys. Ideal for general caching.maxmemory-policy volatile-lru: Evicts keys using LRU among keys that have an expire set. Useful if only some keys are meant to be transient.maxmemory-policy allkeys-random: Evicts random keys among all keys.maxmemory-policy volatile-random: Evicts random keys among keys with an expire set.maxmemory-policy allkeys-lfu: Evicts keys using a Least Frequently Used (LFU) algorithm among all keys (Redis 4.0+).maxmemory-policy volatile-lfu: Evicts keys using LFU among keys that have an expire set (Redis 4.0+).
For most development scenarios where Redis acts as a cache, allkeys-lru is a sensible choice.
# Example in redis.conf or Docker command
maxmemory-policy allkeys-lru
After modifying, remember to restart your Redis instance (brew services restart redis or docker-compose down && docker-compose up -d).
4. Optimize Application Redis Usage
Often, the OOM error is a symptom of how the application interacts with Redis. Optimizing usage can be a more sustainable solution than merely increasing memory limits.
Set Expiration (TTL) for Transient Keys: For cache data or session data that isn't meant to live forever, always set a TTL.
# Via redis-cli SET mycachekey "mycachedvalue" EX 3600 # Expires in 1 hour SETEX anotherkey 600 "shortliveddata" # Shorter syntaxMany Redis client libraries provide direct methods for this (e.g.,
redisClient.set('key', 'value', 'EX', 3600)).Avoid Storing Large Objects Directly as Strings: If you're storing large JSON blobs or serialized objects as single string keys, consider breaking them down into Redis Hashes or storing only necessary, frequently accessed parts.
Use Efficient Data Structures: Redis offers various data structures beyond simple key-value pairs (Hashes, Lists, Sets, Sorted Sets). Using the appropriate structure can significantly reduce memory footprint and improve performance. For example, storing related fields in a single Hash key is often more memory-efficient than storing them as separate String keys.
Monitor Key Cardinality and Patterns: Use
redis-cli --scanto get a snapshot of your key space and identify patterns that might indicate excessive key creation.redis-cli --scan --pattern "*" | head -n 50This helps identify if a particular type of key is consuming too much space.
Avoid the
KEYSCommand in Production (and often development): TheKEYScommand is blocking and iterates over all keys, which can severely impact performance and memory usage, especially on larger datasets. UseSCANinstead for iterating keys.Profiling your application's Redis commands (e.g., using
redis-cli MONITORor built-in client debugging tools) can reveal high-volume or inefficient commands that contribute to memory bloat.
5. Clean Up Existing Data (If Safe)
If your local Redis instance is simply overflowing with old development data and you can afford to lose it (common for local dev), you can flush the database.
NEVER use
FLUSHDBorFLUSHALLon a production Redis instance unless you know exactly what you are doing and have recent backups! This will permanently delete all data.
Flush the current database:
redis-cli FLUSHDBFlush all databases (if you use multiple):
redis-cli FLUSHALLSelective Deletion: If you need to retain some data, identify problematic keys or patterns and delete them selectively:
# Example: Delete all keys matching 'cache:*' pattern redis-cli --scan --pattern "cache:*" | xargs -L 1000 redis-cli DELThis command pipes keys to
DELin batches of 1000 to prevent overwhelming Redis.
By systematically addressing your Redis configuration, eviction policies, and application usage patterns, you can effectively resolve the "Redis OOM command not allowed" error and ensure a stable local development environment.
Our Production Verification Guarantee
Encountering a bug not covered here or running a non-standard kernel configuration? Our solutions are continually refined against real production incidents. Submit an environment trace for our editorial team to replicate.