Magento 2 Redis Setup for Cache and Sessions
Redis is the standard backend for Magento 2 cache and sessions. The file cache that ships by default works for a single developer machine, but on a real store it turns into thousands of small files, slow cache cleans and locking trouble as soon as you add a second web node. This guide covers how to set up Redis for the default cache, the page cache and sessions on Magento Open Source and Adobe Commerce 2.4.8, which settings in app/etc/env.php matter, and the mistakes that cause the most production problems.
Three jobs, three databases
Magento can use Redis for three different things:
- Default cache: configuration, layout, blocks, EAV metadata, reflection data and every other cache type except full page cache.
- Page cache: the built-in full page cache, used when you do not run Varnish.
- Sessions: customer and admin PHP sessions.
Keep them apart. At the very least use separate Redis database numbers. Better still, run sessions on a separate Redis instance from the cache. The reason is eviction. Cache data can be thrown away at any time and Magento will rebuild it. Session data cannot. If both live in one instance with an eviction policy that removes keys under memory pressure, a cache spike can log customers out and empty their carts.
If Varnish handles full page cache, you do not need the Redis page cache at all. Magento only writes to the page cache frontend when the built-in FPC is selected under Stores, Configuration, Advanced, System, Full Page Cache.
Configure the cache with setup:config:set
The quickest way to write the configuration is the CLI. It updates app/etc/env.php for you:
bin/magento setup:config:set \
--cache-backend=redis \
--cache-backend-redis-server=127.0.0.1 \
--cache-backend-redis-port=6379 \
--cache-backend-redis-db=0
bin/magento setup:config:set \
--page-cache=redis \
--page-cache-redis-server=127.0.0.1 \
--page-cache-redis-port=6379 \
--page-cache-redis-db=1
bin/magento setup:config:set \
--session-save=redis \
--session-save-redis-host=127.0.0.1 \
--session-save-redis-port=6380 \
--session-save-redis-db=0
In this example the cache uses an instance on port 6379 and sessions use a second instance on port 6380. Adjust hosts and ports to your setup. After the change, flush the cache once so nothing old is left in the file backend.
What env.php should look like
You will want to edit the file by hand at some point, so it helps to know the structure. A typical cache section looks like this:
'cache' => [
'frontend' => [
'default' => [
'id_prefix' => 'a1b_',
'backend' => 'Magento\\Framework\\Cache\\Backend\\Redis',
'backend_options' => [
'server' => '127.0.0.1',
'database' => '0',
'port' => '6379',
'password' => '',
'compress_data' => '1',
'compression_lib' => ''
]
],
'page_cache' => [
'id_prefix' => 'a1b_',
'backend' => 'Magento\\Framework\\Cache\\Backend\\Redis',
'backend_options' => [
'server' => '127.0.0.1',
'database' => '1',
'port' => '6379',
'password' => '',
'compress_data' => '0'
]
]
],
'allow_parallel_generation' => false
],
A few notes on these keys:
id_prefixis prepended to every key. If two Magento installs share a Redis database, for example staging and production on one box, a unique prefix keeps them from reading each other's data. Separate databases are still the cleaner option.compress_datatrades a little CPU for memory and network traffic. For the default cache it usually pays off because layout and config entries are large and compress well.allow_parallel_generationcontrols whether several processes may build the same config cache at the same time. Leaving it false means one process builds and the others wait, which avoids a pile of PHP workers all regenerating config after a flush.
Session settings that matter
The session block has more options than most people touch, and a few of them are worth understanding:
'session' => [
'save' => 'redis',
'redis' => [
'host' => '127.0.0.1',
'port' => '6380',
'password' => '',
'timeout' => '2.5',
'persistent_identifier' => '',
'database' => '0',
'compression_threshold' => '2048',
'compression_library' => 'gzip',
'log_level' => '1',
'max_concurrency' => '6',
'break_after_frontend' => '5',
'break_after_adminhtml' => '30',
'first_lifetime' => '600',
'bot_first_lifetime' => '60',
'bot_lifetime' => '7200',
'disable_locking' => '0',
'min_lifetime' => '60',
'max_lifetime' => '2592000'
]
],
Session locking
By default the Redis session handler locks a session while a request uses it. Two requests from the same browser at the same moment, for example a page load plus several customer data section calls, wait for each other. max_concurrency limits how many processes can wait on one session lock, and break_after_frontend is how many seconds a request waits before it breaks the lock.
Many stores set disable_locking to 1. Magento does very little that depends on strict session locking, and disabling it removes a class of slow requests that show up as random waits of several seconds in APM traces. Test checkout and cart updates after you change it, especially if you run third party extensions that store a lot in the session.
Bot sessions
Crawlers create a new session on almost every request. bot_first_lifetime and bot_lifetime give those sessions a much shorter life, which keeps the session database from filling up with millions of keys nobody will read again.
log_level
Keep log_level low in production. Higher levels write a line for many session operations and can produce a lot of log noise under load.
Redis server settings
The Magento side is only half of the setup. The Redis server needs its own configuration, and the most important line is the memory policy.
# Cache instance (port 6379)
maxmemory 2gb
maxmemory-policy allkeys-lru
save ""
appendonly no
# Session instance (port 6380)
maxmemory 1gb
maxmemory-policy noeviction
appendonly yes
For the cache instance, allkeys-lru lets Redis evict the least recently used keys when memory is full. That is safe because every cache entry can be rebuilt. Persistence is mostly wasted work for a cache, so turning off RDB snapshots and the append only file saves disk writes.
For sessions, use noeviction and give the instance enough memory. If it fills up, writes fail and you see errors instead of silently losing sessions, which is easier to notice and fix. Persistence is useful here so a Redis restart does not log everyone out.
The sizes above are only placeholders. Measure with redis-cli info memory on your own store and size from the real used_memory plus headroom.
Preloading keys and the L2 cache
On busy stores Redis network traffic becomes noticeable because every request loads the same config and EAV entries. Magento has two features for that.
preload_keys
The Redis backend accepts a preload_keys list in backend_options. Those keys are fetched in one round trip at the start of the request instead of one by one. The key names include your id_prefix, so you find them by running redis-cli monitor on staging for a few requests and picking the keys loaded on every page, such as the EAV entity types and global plugin list.
Two level cache
The second option is the two level cache backend Magento\Framework\Cache\Backend\RemoteSynchronizedCache. Each web node keeps a local copy of cache data, for example in /dev/shm, and Redis is used to check that the local copy is still current:
'default' => [
'id_prefix' => 'a1b_',
'backend' => 'Magento\\Framework\\Cache\\Backend\\RemoteSynchronizedCache',
'backend_options' => [
'remote_backend' => 'Magento\\Framework\\Cache\\Backend\\Redis',
'remote_backend_options' => [
'server' => '10.0.0.5',
'database' => '0',
'port' => '6379',
'compress_data' => '1'
],
'local_backend' => 'Cm_Cache_Backend_File',
'local_backend_options' => [
'cache_dir' => '/dev/shm/'
],
'use_stale_cache' => false
]
],
This helps most when Redis sits on another server and network latency adds up. On a single server with Redis on localhost the gain is small and you add another moving part. Make sure the local directory has room, because /dev/shm lives in RAM.
Checking that it works
A few quick checks after the switch:
redis-cli -p 6379 -n 0 dbsize
redis-cli -p 6380 -n 0 dbsize
redis-cli -p 6379 info stats | grep -E 'keyspace_hits|keyspace_misses|evicted_keys'
ls var/cache var/page_cache
Key counts should grow as you browse the store. The var/cache and var/page_cache folders should stay empty or stop changing. If evicted_keys on the session instance is above zero, something is wrong with its memory policy.
When you clear cache, prefer bin/magento cache:clean over cache:flush. Clean removes Magento's tagged entries. Flush empties the whole storage behind each cache frontend, which is fine when the database is dedicated to Magento cache but destructive if anything else shares it. Never point a cache frontend at the session database. A flush would then log out every customer.
Common problems
- Connection refused or timeouts under load: check
maxclientson the Redis side and thetimeoutin env.php. A slow Redis usually means it is swapping or sharing a CPU with something busy. - Customers logged out at random: sessions and cache in the same instance with an eviction policy, or a session instance that hit its memory limit.
- Slow requests with long waits on session read: session locking. Look at the waterfall in your APM and consider disabling locking.
- Cache cleans that take minutes: usually a very large number of tags in one database. Separating page cache from the default cache helps, and so does moving full page cache to Varnish.
Redis is one piece of the stack. For the rest of the server tuning see the guides on PHP-FPM tuning and Varnish full page cache, and the env.php and config.php explainer for the other sections of the file.
FAQ
Should Magento sessions and cache use the same Redis instance?
It works, but a separate instance for sessions is safer. Cache needs an eviction policy and sessions must never be evicted, and one instance can only have one policy.
Do I need Redis page cache if I use Varnish?
No. With Varnish as the full page cache application, Magento does not store pages in the page_cache frontend, so you only need Redis for the default cache and sessions.
Is it safe to disable session locking in Magento 2?
For most stores yes, and it removes slow requests caused by parallel calls waiting on the same session. Test cart, checkout and any extension that writes heavily to the session before you roll it out.
What is the difference between cache:clean and cache:flush with Redis?
cache:clean removes Magento cache entries by type and tag. cache:flush empties the storage behind the cache frontends, so anything else stored in that Redis database is lost too.
I am available for freelance Magento and Adobe Commerce work, including server and cache setup. If you need help with this, get in touch.
Related articles
Magento 2 Cache Types Explained: Clean, Flush, Custom
What each Magento 2 cache type stores, the real difference between cache:clean and cache:flush, invalidated caches, and how to add your own cache type.
Magento 2 Blackfire Profiling: Pages, CLI and Tests
Profile Magento 2 with Blackfire: probe and agent setup, profiling pages and bin/magento commands, reading call graphs and adding performance assertions.
Magento 2 CDN: Cloudflare vs Fastly Setup Guide
Put a CDN in front of Magento 2: Fastly as an edge full page cache, Cloudflare for static and media, real client IP, purging and settings that break things.
Magento 2 Code Review Checklist for Pull Requests
A practical Magento 2 code review checklist: DI and architecture, performance traps, security and escaping, database changes, frontend, tests and deploy impact.