Skip to content
Pro Analyzer — Available with ShieldCI Pro

Redis Eviction Policy Analyzer

Analyzer IDCategorySeverityTime To Fix
redis-eviction-policy✅ ReliabilityHigh10 minutes

What This Checks

  • Queries the live Redis server for the current maxmemory-policy via CONFIG GET
  • Validates the eviction policy is appropriate based on how your application uses Redis (cache, queue, session, Horizon)
  • Detects when a cache-only Redis server uses noeviction (causes write errors when memory is full)
  • Detects when Redis stores persistent data (queues, sessions, Horizon) with an eviction policy that could delete jobs or sessions
  • Detects when multiple named connections (e.g. cache and default) resolve to the same host:port — since eviction policy is server-level, a cache-only connection is not flagged if its server also serves persistent data (changing the policy there would be dangerous)
  • Checks whether maxmemory is configured (warns if unlimited)
  • Monitors memory usage and warns when consumption exceeds 90% of the configured limit
  • Only runs in production and staging environments (skipped in CI and local)

Why It Matters

  • Data loss: If Redis stores queue jobs or sessions and uses an LRU/LFU eviction policy, pending jobs can be silently deleted when memory pressure occurs
  • Write failures: The default noeviction policy returns errors on writes when memory is full -- if Redis is only used for caching, this causes application errors instead of gracefully evicting stale entries
  • Silent degradation: Users get logged out unexpectedly when session data is evicted, or background jobs disappear without any error in application logs
  • Memory exhaustion: Without a maxmemory limit, Redis can consume all available system memory, causing OOM kills in containerized environments
  • Production outages: Memory-related Redis failures cascade to every part of the application that depends on it

How to Fix

Quick Fix (2 minutes)

Check and set the eviction policy directly on your Redis server:

bash
# Check current policy
redis-cli CONFIG GET maxmemory-policy

# For cache-only servers: allow eviction of least-frequently-used keys
redis-cli CONFIG SET maxmemory-policy allkeys-lfu

# For servers storing persistent data (queues, sessions): prevent eviction
redis-cli CONFIG SET maxmemory-policy noeviction

# Set a memory limit (required for eviction policies to work)
redis-cli CONFIG SET maxmemory 2gb

# Persist changes to redis.conf
redis-cli CONFIG REWRITE

Proper Fix (10 minutes)

1: Separate Redis Instances by Workload

The best practice is to use different Redis servers (different host or port) for cache vs persistent data. Different logical databases on the same server (database: 0 vs database: 1) are not sufficientmaxmemory-policy is a server-level setting and applies to all databases on the instance simultaneously.

php
// config/database.php
'redis' => [
    'client' => env('REDIS_CLIENT', 'phpredis'),

    // Cache instance - use allkeys-lfu eviction
    'cache' => [
        'host' => env('REDIS_CACHE_HOST', '127.0.0.1'),
        'port' => env('REDIS_CACHE_PORT', 6380),
        'database' => env('REDIS_CACHE_DB', 0),
    ],

    // Queue/Session instance - use noeviction
    'persistent' => [
        'host' => env('REDIS_PERSISTENT_HOST', '127.0.0.1'),
        'port' => env('REDIS_PERSISTENT_PORT', 6381),
        'database' => env('REDIS_PERSISTENT_DB', 0),
    ],
],
php
// config/cache.php
'redis' => [
    'driver' => 'redis',
    'connection' => 'cache',  // Uses cache Redis instance
],
php
// config/queue.php
'redis' => [
    'driver' => 'redis',
    'connection' => 'persistent',  // Uses persistent Redis instance
    'queue' => 'default',
    'retry_after' => 90,
],
php
// config/session.php
'driver' => 'redis',
'connection' => 'persistent',  // Uses persistent Redis instance

2: Configure Redis Server Settings

For the cache Redis instance (redis-cache.conf):

ini
maxmemory 2gb
maxmemory-policy allkeys-lfu

For the persistent Redis instance (redis-persistent.conf):

ini
maxmemory 1gb
maxmemory-policy noeviction
appendonly yes

3: Environment-Specific Configuration

bash
# .env (production)
REDIS_CACHE_HOST=redis-cache.internal
REDIS_CACHE_PORT=6379
REDIS_PERSISTENT_HOST=redis-persistent.internal
REDIS_PERSISTENT_PORT=6379

4: Monitor Memory Usage

Set up monitoring to alert before Redis reaches its memory limit:

bash
# Check memory usage
redis-cli INFO memory | grep used_memory_human
redis-cli INFO memory | grep maxmemory_human

# Check eviction stats
redis-cli INFO stats | grep evicted_keys

Eviction Policy Reference

PolicyBehaviorBest For
noevictionReturns error on write when fullQueues, sessions, persistent data
allkeys-lfuEvicts least frequently used keysGeneral-purpose cache (Redis 4+)
allkeys-lruEvicts least recently used keysGeneral-purpose cache
volatile-lfuEvicts LFU keys with TTL setMixed cache + persistent on same instance
volatile-lruEvicts LRU keys with TTL setMixed cache + persistent on same instance
volatile-ttlEvicts keys closest to expiryTime-sensitive cache entries
allkeys-randomEvicts random keysUniform access patterns

ShieldCI Configuration

This analyzer is automatically skipped in CI environments ($runInCI = false) and only runs in production and staging environments.

Why skip in CI and development?

  • Eviction policy checks require a live Redis connection with access to the CONFIG GET command
  • CI and local Redis instances are typically ephemeral and not configured to reflect production settings
  • Eviction policy mismatches only matter when Redis is under real memory pressure

Environment Detection: The analyzer checks your Laravel APP_ENV setting and only runs when it maps to production or staging. Custom environment names can be mapped in config/shieldci.php:

php
// config/shieldci.php
'environment_mapping' => [
    'production-us' => 'production',
    'production-blue' => 'production',
    'staging-preview' => 'staging',
],

Examples:

  • APP_ENV=production → Runs (no mapping needed)
  • APP_ENV=production-us → Maps to production → Runs
  • APP_ENV=local → Skipped (not production/staging)

Managed Redis (ElastiCache, Upstash, Memorystore, Redis Cloud): Many managed Redis providers restrict the CONFIG GET command via ACL. The analyzer detects this and skips analysis for those connections rather than emitting false positives — no action required on your part.

References