Two cache layers, two different jobs
Redis and Varnish are often pitted against each other in Magento discussions, yet they solve fundamentally different problems. Redis is the cache and session backend for object cache and full page cache storage, Varnish is the HTTP layer in front that delivers whole pages before Magento even starts. This article explains the clean role split.
Table of Contents
- 1. The common misconception: Redis or Varnish
- 2. The role of Redis: cache backend and session store
- 3. The role of Varnish: the HTTP layer in front of Magento
- 4. The path of a request through both layers
- 5. Varnish configuration for Magento
- 6. Cache invalidation: how both systems work together
- 7. ESI: dynamic content inside static pages
- 8. Magento without Varnish: when it is enough
- 9. Redis and Varnish compared directly
- 10. Summary
- 11. FAQ
1. The common misconception: Redis or Varnish
In many discussions about Magento performance, the question is asked whether a store needs Redis or Varnish, as if both were interchangeable alternatives for the same job. This framing is already wrong: Redis and Varnish operate at completely different levels of the request lifecycle and solve different problems. The question should not be which of the two systems to use, but how to combine both sensibly.
Redis is an in-memory data store used by Magento as a backend for the object cache, optionally the full page cache storage, and session management. It operates inside the PHP application and is addressed directly by Magento code. Varnish, on the other hand, is a standalone HTTP reverse proxy that sits IN FRONT of the web server and PHP-FPM, caching complete HTTP responses. A request answered by Varnish from cache never reaches PHP, and therefore never reaches Redis either.
This fundamental distinction is the key to understanding it: Varnish prevents Magento and Redis from being queried at all, while Redis speeds up Magento when it is actually queried. Both systems are complementary, not competing, and a production ready Magento store with serious traffic typically uses both at the same time.
2. The role of Redis: cache backend and session store
Redis takes on three clearly separated tasks in Magento. First, the object cache, which stores computed data such as layout XML merges, configuration values, EAV attribute metadata and block data. This cache is read on every request, regardless of whether the request comes from a logged in customer or a guest, and regardless of whether the page ultimately gets cached by Varnish or not.
Second, Redis can serve as the storage backend for the full page cache when no Varnish is in use. In this mode, Magento renders complete HTML pages and stores them in Redis, so a repeated request can serve the same page without re-rendering, although the request still has to pass through PHP and Magento, just without the expensive rendering work. Third, Redis stores sessions, so cart contents, login status and personalized data persist across multiple requests.
Important: all three roles of Redis assume the request actually reaches PHP. Redis cannot prevent Magento from being started at all, it can only reduce the effort inside Magento once it is running.
3. The role of Varnish: the HTTP layer in front of Magento
Varnish sits architecturally in front of the entire Magento stack, usually directly behind the load balancer or even in its place. When a request arrives, Varnish first checks whether a matching response already exists in its own in-memory cache. If so, Varnish serves the complete HTTP response directly, without Nginx, PHP-FPM, Magento or Redis ever being involved. This response time is typically in the low single digit millisecond range, because Varnish is written in C and works exclusively with memory.
The decisive architectural advantage of Varnish is that it completely bypasses all PHP processing for cached pages. While a Redis backed object cache speeds up PHP processing, Varnish eliminates it entirely for full page cache hits. The difference becomes especially noticeable under high traffic load: a Magento setup with only Redis, no Varnish, can hit PHP-FPM worker capacity limits under thousands of concurrent requests despite a fast object cache, because every request still occupies a PHP process. With Varnish in front, anonymous, cacheable page views are fully decoupled from PHP-FPM.
4. The path of a request through both layers
To understand the role split concretely, it helps to look at the actual path of a request. On a Varnish cache hit, the path ends after just a few milliseconds without Magento or Redis being involved at all. On a Varnish cache miss, for example for a not yet cached product page or a personalized request, the request gets forwarded to the web server, which hands it to PHP-FPM and thus to Magento.
Inside Magento, the object cache in Redis then kicks in to avoid expensive computations, while the session is also read from Redis to restore the user context. After complete processing, Magento returns the HTML response to Varnish, which, if cacheable, stores it for future requests while simultaneously serving it to the current client.
# Request path visualization via response headers
curl -sI https://shop.example.com/catalog/category/view/id/42 | grep -iE "x-cache|x-magento-cache|age"
# Varnish cache hit: request never reached PHP
# X-Magento-Cache-Debug: HIT
# Age: 340
# Varnish cache miss: request went through PHP and Redis object cache
# X-Magento-Cache-Debug: MISS
# Age: 0
# Check Redis object cache hit ratio independently
redis-cli -p 6379 info stats | grep -E "keyspace_hits|keyspace_misses"
5. Varnish configuration for Magento
Magento generates its own VCL configuration file via bin/magento varnish:vcl:generate, which serves as the starting point for the Varnish cache layer. This file defines which requests are cacheable, how cache tags are used for invalidation, and how backend health checks are configured. It usually only needs to be generated once and rarely adjusted afterward, except for individual requirements such as additional cookies that affect cacheability.
# Generate the Varnish VCL configuration matching the running Magento instance
bin/magento varnish:vcl:generate --export-version=6 --access-list="10.0.0.0/24" > /etc/varnish/default.vcl
# Point Magento's cache configuration to Varnish as the caching application
# app/etc/env.php
# 'system' => [
# 'default' => [
# 'system' => [
# 'full_page_cache' => [
# 'caching_application' => '2',
# 'varnish' => [
# 'access_list' => '10.0.0.0/24',
# 'backend_host' => 'nginx',
# 'backend_port' => '80',
# ],
# ],
# ],
# ],
# ],
# Reload Varnish with the new configuration
varnishadm vcl.load new_config /etc/varnish/default.vcl
varnishadm vcl.use new_config
After every deployment that affects the Magento cache configuration, the VCL file must be regenerated and Varnish reloaded, otherwise Varnish keeps running with a stale configuration that does not know about new cache tags or changed backend settings. This step belongs firmly in every Magento deployment pipeline that uses Varnish.
6. Cache invalidation: how both systems work together
When a product or category is changed in Magento, both the Redis object cache and the Varnish full page cache need to be invalidated, but through different mechanisms. The object cache in Redis is invalidated via cache tags, managed internally by Magento and automatically removed when an entity is saved. Varnish, on the other hand, is invalidated via HTTP PURGE requests that Magento sends to Varnish as soon as relevant cache tags are affected.
In a correctly configured environment, this dual invalidation runs automatically and in sync: when a product is saved, Magento removes the affected object cache entries in Redis and simultaneously sends a PURGE request to Varnish for all pages referencing that product. A common configuration mistake is that Varnish only accepts PURGE requests from certain IP addresses defined in the access_list parameter. If the Magento application server's IP is missing from this list, PURGE requests fail and Varnish keeps serving stale pages even though the Redis object cache has already been correctly updated.
# Manually verify the invalidation chain after a product save
# 1. Check the Redis object cache no longer holds the stale tag
redis-cli -p 6379 keys "*catalog_product_42*" | head -n 5
# 2. Confirm Varnish received and processed the PURGE request
varnishlog -q "ReqMethod eq \"PURGE\""
# 3. If PURGE requests fail, check the access list in the VCL
grep -A 5 "acl purge" /etc/varnish/default.vcl
# 4. Manually trigger a purge for a specific URL as a fallback
curl -X PURGE https://shop.example.com/catalog/product/view/id/42 \
-H "Host: shop.example.com"
7. ESI: dynamic content inside static pages
A particular challenge for Varnish is personalized content on otherwise static pages, such as the cart counter in the header or personalized product recommendations. If the entire page were excluded from cacheability because of these small dynamic parts, the whole performance advantage of Varnish would be lost. The solution is Edge Side Includes: Varnish caches the static main page but leaves defined placeholders open, which get reloaded separately from Magento and Redis on every request.
These ESI blocks are themselves small requests that pass through the PHP stack and benefit from the Redis object cache, but are significantly smaller and faster than a full page processing cycle. Magento uses ESI by default for elements like the mini cart, so the rest of the page, such as product description and image gallery, can be fully cached by Varnish while only the small personalized part gets reloaded on every request.
# ESI tag as rendered inside an otherwise fully cached Magento page
# <esi:include src="/checkout/cart/miniCartCustomerData" />
# Confirm ESI processing is enabled in Varnish VCL
grep -A 3 "set beresp.do_esi" /etc/varnish/default.vcl
# Trace how often the ESI sub-request hits Redis object cache vs a fresh render
redis-cli -p 6379 monitor | grep -i "block_html\|mini_cart" &
curl -s https://shop.example.com/ > /dev/null
8. Magento without Varnish: when it is enough
Not every Magento store strictly needs Varnish. For very small stores with low traffic, few concurrent users and no traffic spikes, the internal full page cache with Redis as the backend can deliver sufficient performance without taking on the additional operational complexity of a separate Varnish layer. The internal full page cache is slower than Varnish, since it still passes through PHP, but is often completely sufficient for low load spikes.
Once a store has to regularly serve hundreds of concurrent requests, for example during marketing campaigns or seasonal peaks like Black Friday, the difference becomes clearly noticeable. PHP-FPM workers are a limited, expensive resource, while Varnish serves HTTP responses from memory with minimal resource consumption. For stores with significant traffic, Varnish is practically always the better investment compared to additional PHP-FPM workers or larger application servers.
// app/etc/env.php: internal full page cache using Redis, no Varnish in front
'system' => [
'default' => [
'system' => [
'full_page_cache' => [
// caching_application 1 = built-in FPC backed by Redis
'caching_application' => '1',
],
],
],
],
'cache' => [
'frontend' => [
'page_cache' => [
'backend' => 'Cm_Cache_Backend_Redis',
'backend_options' => [
'server' => '10.0.1.20',
'port' => '6381',
'compress_data' => 1,
],
],
],
],
9. Redis and Varnish compared directly
The following table compares both systems along their most important characteristics to make the complementary roles tangible.
| Characteristic | Redis | Varnish |
|---|---|---|
| Position in the stack | Inside the PHP application | In front of web server and PHP-FPM |
| What gets cached | Object data, sessions, HTML fragments | Complete HTTP responses |
| PHP involvement | Always, Redis is addressed by PHP | None on a cache hit |
| Suitable for sessions | Yes, core function | No, no session storage |
| Typical response time on hit | A few milliseconds plus PHP overhead | Under one millisecond |
The table makes it clear: Redis and Varnish are not in competition with each other, but cover different sections of the request lifecycle. A Magento store with serious traffic benefits from both simultaneously, because they solve different bottlenecks.
10. Summary
Redis and Varnish are not competing alternatives, but two complementary building blocks of a well thought out Magento caching architecture. Redis acts inside the PHP application as a fast backend for object cache and sessions, while Varnish sits as an HTTP layer in front and delivers complete pages without PHP or Redis ever being addressed. This role split is the reason both systems are used together in production ready Magento setups.
Invalidation of both layers must run in sync, so neither stale object cache entries nor stale full page cache pages get served. ESI solves the problem of personalized content inside static, Varnish cached pages by reloading only the small dynamic parts on every request. Whoever deploys both systems correctly in their respective roles achieves performance that neither system alone could reach.
Redis vs. Varnish in Magento: The Key Points at a Glance
Redis
Cache backend inside Magento for object cache and sessions, always addressed by PHP.
Varnish
HTTP layer in front of Magento, serves complete pages without PHP involvement on a cache hit.
Invalidation
Must run in sync: clear Redis cache tags and send Varnish PURGE requests.
Combination
Deploy both systems together, they solve different bottlenecks in the request lifecycle.