Back to Blog

How to speed up Drupal with the right caches: OPcache, APCu, and a shared backend (Redis or Memcached)

2025-08-1310 min read

If your Drupal site feels slow, caching is usually the fix. Not a single fix, though. Different layers solve different problems. That is why OPcache, APCu, and a shared backend such as Redis or Memcached often show up together. Each one speeds up a specific part of the stack. Use them well and Drupal becomes snappy. Use them poorly and it still drags.

Warning: pick one shared backend for Drupal cache bins. Use Redis or Memcached, not both for the same bins.

At a glance: must do vs advanced

  • Must do: Enable OPcache in PHP. Turn on APCu for local caches. Choose one shared backend for bins on multi server setups.
  • Advanced: Map specific bins, tune Redis client timeouts, adjust Memcached item size, compress large Redis values, size pools based on real usage.

Quick decision guide

SetupMust doShared backendBest forNotes
Single serverOPcache + APCuOptionalSmall sites on one nodeDB cache may be fine. Add Redis or Memcached if traffic grows.
Multiple serversOPcache + APCuRedis or MemcachedLoad-balanced clustersUse one shared backend for render, dynamic page cache, page, default, data.
High variability contentOPcacheRedisComplex tagging and invalidationStructures and persistence options help.
Lean and simpleOPcacheMemcachedPure caching with minimal overheadVery fast, ephemeral by design.

What each cache does

  • OPcache: Speeds up PHP itself by caching compiled scripts.
  • APCu: Local, per server key value cache for tiny lookups.
  • Redis: Shared in memory data store for caches, queues, locks, sessions.
  • Memcached: Shared in memory key value cache, very simple and fast.

How these fit into Drupal

  • OPcache: Enable at the PHP layer. Not a Drupal module.
  • APCu: Serve local caches and bootstrap data.
  • Redis or Memcached: Map render, dynamic page cache, page, default, data to the shared backend. Also support sessions, locks, and queues.

Related: State cache (Drupal 10.3+, on by default in Drupal 11). See the separate post for details: Speed up the Drupal backend with $settings['state_cache'].

Pro Tip: On multi-server setups, keep bootstrap in APCu for ultra low latency, and move the rest to the shared backend.

settings.php quick recipes

Paste, then adapt.

Redis

Drupal integration

$settings['container_yamls'][] = 'modules/contrib/redis/redis.services.yml';
$settings['redis.connection']['interface'] = 'PhpRedis';
$settings['redis.connection']['host'] = '127.0.0.1';
$settings['redis.connection']['port'] = 6379;
$settings['cache']['default'] = 'cache.backend.redis';
$settings['cache']['bins']['render'] = 'cache.backend.redis';
$settings['cache']['bins']['dynamic_page_cache'] = 'cache.backend.redis';
$settings['cache']['bins']['page'] = 'cache.backend.redis';

Performance tuning

// Optional compression
$settings['redis_compress_length'] = 100;
$settings['redis_compress_level'] = 1;
// Client timeouts (PhpRedis)
$settings['redis.connection']['timeout'] = 1.0;
$settings['redis.connection']['read_timeout'] = 1.0;
$settings['redis.connection']['retry_interval'] = 100;
$settings['redis.connection']['persistent'] = TRUE;
  • container_yamls: Registers Redis services.
  • interface: Chooses client. PhpRedis is native extension.
  • host/port: Specifies connection target. Prefer Unix socket on same host.
  • cache.default: Sets default backend for unmapped bins.
  • bins: Maps specific bins to Redis.
  • compress_length/level: Compresses large values to save memory.
  • timeouts/persistent: Sets connect/read timeouts and reuses connections.

Memcached

Drupal integration

$settings['container_yamls'][] = 'modules/contrib/memcache/memcache.services.yml';
$settings['memcache']['servers']['127.0.0.1:11211'] = 'default';
$settings['memcache']['bins']['render'] = 'default';
$settings['memcache']['bins']['dynamic_page_cache'] = 'default';
$settings['memcache']['bins']['page'] = 'default';
$settings['cache']['default'] = 'cache.backend.memcache';
  • container_yamls: Registers Memcache services.
  • servers: Defines server list and pool name.
  • bins: Maps bins to a pool.
  • cache.default: Sets default backend for unmapped bins.

APCu for local bins

// Requires APCu backend module
$settings['cache']['bins']['bootstrap'] = 'cache.backend.apcu';
  • bootstrap: Keeps hot bootstrap data in process for lowest latency.

Runtime/server settings (outside settings.php)

PHP settings (php.ini)

OPcache

opcache.enable=1
opcache.enable_cli=0
opcache.memory_consumption=192
opcache.max_accelerated_files=16229
opcache.validate_timestamps=0
opcache.revalidate_freq=0
opcache.interned_strings_buffer=16
opcache.fast_shutdown=1
  • opcache.enable: Turns OPcache on for FPM or Apache.
  • opcache.enable_cli: Keeps OPcache off for CLI.
  • opcache.memory_consumption: Allocates memory pool for compiled scripts.
  • opcache.max_accelerated_files: Sets hash table size.
  • opcache.validate_timestamps: Checks file timestamps for changes. Set to 0 for build-once deploys.
  • opcache.revalidate_freq: Sets seconds between timestamp checks when validate_timestamps = 1.
  • opcache.interned_strings_buffer: Allocates memory for shared strings.
  • opcache.fast_shutdown: Enables faster request shutdown.

APCu

apc.enabled=1
apc.enable_cli=0
apc.shm_size=128M
apc.ttl=0
apc.gc_ttl=3600
  • apc.enabled: Turns APCu on for FPM.
  • apc.enable_cli: Keeps APCu off for CLI.
  • apc.shm_size: Sets total shared memory.
  • apc.ttl: Sets default TTL for entries.
  • apc.gc_ttl: Sets time to keep orphaned entries.

Redis server (redis.conf)

maxmemory 2gb
maxmemory-policy allkeys-lru
timeout 1
tcp-keepalive 60
  • maxmemory: Sets memory cap.
  • maxmemory-policy: Sets eviction behavior when full.
  • timeout: Sets idle client timeout in seconds.
  • tcp-keepalive: Sets interval for keepalive probes.

Memcached server (flags)

memcached -m 2048 -I 4m -f 1.25 -o slab_reassign,slab_automove
  • -m: Sets total memory in MB.
  • -I: Sets max item size.
  • -f: Sets growth factor for slab classes.
  • -o slab_reassign,slab_automove: Enables slab rebalancing.

Sizing quick rules

CacheKey settingQuick rule (MB)
OPcacheopcache.memory_consumptionMB = (codebase_MB × 3) + 32
OPcacheopcache.max_accelerated_files≈ 1.5 × PHP files (use 10000, 16229, 32531)
APCuapc.shm_sizeMB ≈ (keys × (avg_item_bytes + 100) × 1.2) ÷ 1,000,000
RedismaxmemoryMB ≈ (items × (avg_item_bytes + 50) × 1.3) ÷ 1,000,000
Memcached-mMB ≈ (items × avg_item_bytes × 1.3) ÷ 1,000,000
Memcached-IStart at 4 MB; increase if needed

Common myths

  1. Myth: OPcache caches HTMLTruth: It caches compiled PHP code.
  2. Myth: APCu works across serversTruth: It is local to one server process.
  3. Myth: Redis is always better than MemcachedTruth: Pick based on needs.
  4. Myth: Cache misses mean something is brokenTruth: Misses happen and warm up with traffic.

Quick setup checklist

  • OPcache:
    • Enable the extension in PHP.
    • Tune memory size and revalidation settings for production.
    • Ensure enough opcache.memory_consumption to hold your codebase.
  • APCu:
    • Install the PHP extension.
    • Confirm CLI and FPM settings if you run both.
    • Size apc.shm_size with headroom to avoid evictions.
  • Redis:
    • Install the server and PHP extension.
    • Add the Drupal Redis module and map the right cache bins.
    • Set client timeouts and consider sessions, locks, and queues.
  • Memcached:
    • Install the server and PHP extension.
    • Add the Drupal Memcache module and map the bins you want.
    • Set -I for max item size; ensure the app tolerates cache loss.

Avoid these traps

  • Avoid mixing Redis and Memcached for the same bin.
  • Avoid undersizing caches. Watch evictions and hit rate.
  • Avoid over-caching. Focus on expensive, reusable data.
  • Avoid breaking invalidation. Respect cache tags and contexts.

How to measure success

  • Response time trends: Time to first byte should drop after warmup.
  • Database load: Fewer queries per request and lower CPU on the database.
  • Hit ratio: Track cache hit rates. If hit rates stay low, review bin mapping and TTLs.
  • Error logs: Watch for connection errors or timeouts from Redis or Memcached.

Final thoughts

Start with OPcache, add APCu, then Redis or Memcached for shared bins. Keep it simple, measure results, and tune.