Entscheidungskriterien für die Praxis
Magento 2 bringt mit dem eingebauten Full Page Cache bereits eine funktionierende Caching-Lösung mit, doch viele Projekte setzen zusätzlich Varnish vor den Shop, ohne die tatsächlichen Anforderungen zu prüfen. Dieser Beitrag vergleicht beide Ansätze anhand von Traffic-Volumen, Hosting-Setup und Team-Kompetenz und zeigt an VCL-Beispielen, Purge-Strategien und Monitoring-Kommandos, wann sich der zusätzliche Betriebsaufwand von Varnish wirklich lohnt.
Inhaltsverzeichnis
- 1. Einordnung: zwei Cache-Ebenen, ein Missverständnis
- 2. Architektur des eingebauten Full Page Cache ohne Varnish
- 3. Architektur mit Varnish: VCL, Debug-Header und Purge-Flow
- 4. Entscheidungskriterien für die Praxis
- 5. VCL-Anpassungen speziell für Magento
- 6. Cache-Invalidierung und Purge-Strategien im Vergleich
- 7. Monitoring und Debugging
- 8. Migration zwischen eingebautem Cache und Varnish
- 9. Varnish vs. eingebauter Cache im direkten Vergleich
- 10. Zusammenfassung
- 11. FAQ
1. Einordnung: zwei Cache-Ebenen, ein Missverständnis
Wer ein neues Magento-2-Projekt aufsetzt, stößt fast zwangsläufig auf die Frage: Brauchen wir Varnish vor dem Shop? Diese Frage ist in den meisten Fällen falsch gestellt, weil sie zwei unterschiedliche Dinge vermischt. Magento bringt bereits einen eingebauten Full Page Cache mit, der ganze Seiten als HTML zwischenspeichert und bei wiederholten Anfragen ausliefert, ohne die komplette Applikation neu zu rendern. Varnish ist keine Alternative zu diesem Konzept, sondern eine andere Implementierung derselben Idee: eine vorgeschaltete Instanz, die HTTP-Antworten cached, bevor eine Anfrage überhaupt bei PHP ankommt.
Der eigentliche Unterschied liegt nicht in der Frage "cachen oder nicht cachen", sondern darin, wo im Request-Pfad das Caching stattfindet. Der eingebaute Cache arbeitet innerhalb des PHP-Prozesses und wird über die Magento-Cache-Frontends gesteuert, während Varnish als eigenständiger Reverse-Proxy vor dem gesamten Webserver-Stack sitzt und Anfragen abfängt, bevor Nginx oder Apache überhaupt involviert werden. Diese architektonische Verschiebung hat Konsequenzen für Performance, Betriebsaufwand und die Komplexität der Infrastruktur, die weit über die reine Frage nach der Cache-Hit-Rate hinausgehen.
Statt "Brauche ich Varnish?" sollte die Frage lauten: Welche Cache-Ebene passt zu unserem Traffic-Profil, unserem Hosting-Setup und der Kompetenz im Team, die VCL-Konfiguration dauerhaft zu pflegen? Genau dieser Entscheidungsrahmen ist Gegenstand der folgenden Abschnitte, mit konkreten Konfigurationsbeispielen für beide Ansätze.
2. Architektur des eingebauten Full Page Cache ohne Varnish
Ohne Varnish übernimmt Magento das komplette HTTP-Caching selbst. Gesteuert wird das über zwei Konfigurationsblöcke in app/etc/env.php: den Cache-Typ full_page, der grundsätzlich aktiviert sein muss, und das Cache-Frontend, das festlegt, wo die gerenderten Seiten physisch gespeichert werden, üblicherweise Redis oder das Dateisystem über Cm_Cache_Backend_File. Bleibt der Schlüssel http_cache_hosts leer, geht Magento davon aus, dass kein externer Reverse-Proxy existiert, und übernimmt die komplette Auslieferung gecachter Seiten selbst.
Technisch läuft das über Magento\Framework\App\PageCache\Kernel: Bei jedem Request prüft Magento zuerst, ob für die aktuelle URL, den Vary-Kontext und die Cookie-Konstellation bereits eine gecachte Antwort existiert. Ist das der Fall, wird die gespeicherte HTML-Antwort direkt zurückgegeben, allerdings erst nachdem der PHP-Prozess gestartet und ein Teil des Bootstraps durchlaufen wurde. Das ist der zentrale Unterschied zu Varnish: Der eingebaute Cache spart die teure Rendering-Arbeit, aber nicht den kompletten PHP-Bootstrap-Overhead pro Request.
Für viele Shops mit moderatem Traffic ist genau das ausreichend. Der eingebaute Cache benötigt keinen zusätzlichen Dienst, keine offene Portfreigabe und keinen root-Zugriff auf den Server, was ihn zur einzig praktikablen Option auf Shared- oder Managed-Hosting-Umgebungen macht, in denen kein eigener Reverse-Proxy betrieben werden kann.
<?php
// app/etc/env.php - built-in Full Page Cache without Varnish
return [
'cache_types' => [
'config' => 1,
'layout' => 1,
'block_html' => 1,
'full_page' => 1,
'translate' => 1,
],
'cache' => [
'frontend' => [
'page_cache' => [
'id_prefix' => 'a1b_',
'backend' => 'Cm_Cache_Backend_File',
'backend_options' => [
'cache_dir' => '/var/www/html/var/page_cache',
],
],
],
],
// Empty array signals to Magento: no reverse proxy, use built-in cache
'http_cache_hosts' => [],
];
3. Architektur mit Varnish: VCL, Debug-Header und Purge-Flow
Sobald Varnish als Reverse-Proxy vor Magento läuft, ändert sich der Request-Pfad grundlegend. Der Eintrag http_cache_hosts in env.php wird mit Host und Port des Varnish-Servers befüllt, und Magento generiert über bin/magento varnish:vcl:generate eine VCL-Datei auf Basis des mitgelieferten Templates. Diese VCL definiert, welche Requests gecacht werden dürfen, wie Cookies behandelt werden und wie Purge-Anfragen verarbeitet werden. Anders als beim eingebauten Cache landet ein gecachter Request bei aktivem Varnish FPC nie beim PHP-Prozess, sondern wird komplett von Varnish aus dem Arbeitsspeicher beantwortet.
Ein zentrales Diagnosewerkzeug ist der Header X-Magento-Cache-Debug, den Magento selbst setzt und der Werte wie HIT oder MISS trägt. Dieser Header funktioniert unabhängig davon, ob Varnish im Spiel ist, aber erst in Kombination mit Varnish zeigt er den vollen Effekt: Bei einem HIT hat die Anfrage den PHP-Prozess überhaupt nicht erreicht. Für Invalidierungen sendet Magento HTTP-PURGE-Requests mit dem Header X-Magento-Tags-Pattern an Varnish, sobald sich relevante Entitäten wie Produkte, Kategorien oder CMS-Blöcke ändern. Die VCL muss diese PURGE-Methode explizit erlauben und über eine ACL auf vertrauenswürdige Absender-IPs beschränken.
Der Purge-Flow läuft also komplett außerhalb des normalen Seitenaufrufs: Ein Redakteur speichert ein Produkt, ein Magento-Observer löst die Tag-Invalidierung aus, ein PURGE-Request geht an Varnish, und Varnish entfernt anhand des Tag-Patterns exakt die betroffenen Cache-Einträge, ohne den restlichen Cache zu leeren. Dieser granulare Mechanismus ist einer der Hauptgründe, warum Varnish bei häufigen Content-Änderungen dem eingebauten Cache überlegen ist.
sub vcl_recv {
# Allow PURGE only from trusted Magento application servers
if (req.method == "PURGE") {
if (!client.ip ~ purge_acl) {
return (synth(405, "Not allowed"));
}
return (purge);
}
# Never cache admin, checkout or customer account requests
if (req.url ~ "^/(admin|checkout|customer)") {
return (pass);
}
unset req.http.X-Forwarded-For;
set req.http.X-Forwarded-For = client.ip;
return (hash);
}
sub vcl_backend_response {
# Surface Magento cache tags for tag-based purging
if (beresp.http.X-Magento-Tags) {
set beresp.http.X-Magento-Tags-Pattern = beresp.http.X-Magento-Tags;
}
set beresp.http.X-Magento-Cache-Debug = "MISS";
set beresp.grace = 3600s;
return (deliver);
}
4. Entscheidungskriterien für die Praxis
Traffic-Volumen ist das offensichtlichste Kriterium, aber nicht das einzige. Ein Shop mit wenigen tausend Sessions pro Tag merkt den PHP-Bootstrap-Overhead des eingebauten Caches kaum, während ein Shop mit mehreren hunderttausend Requests pro Tag jede eingesparte Millisekunde Rendering-Zeit im TTFB direkt spürt. Faustregel aus der Praxis: Ab spürbaren Lastspitzen im dreistelligen Requests-pro-Sekunde-Bereich beginnt der PHP-Bootstrap-Overhead des eingebauten Caches, gegenüber der praktisch bootstrap-freien Auslieferung durch Varnish, ins Gewicht zu fallen.
Das Hosting-Setup entscheidet oft schon vorab, ob die Frage überhaupt gestellt werden kann. Auf Shared- oder klassischem Managed-Hosting ohne root-Zugriff und ohne eigenen Reverse-Proxy-Port lässt sich Varnish in der Regel gar nicht betreiben, hier bleibt nur der eingebaute Cache. Bei dediziertem Hosting, VPS oder Kubernetes-Clustern ist die technische Hürde deutlich niedriger, wodurch die Entscheidung stärker von TTFB-Zielen und Infrastruktur-Komplexität abhängt als von harten technischen Grenzen.
Team-Kompetenz ist der am häufigsten unterschätzte Faktor. Eine VCL-Konfiguration will gepflegt werden: bei jedem Magento-Upgrade sollte geprüft werden, ob sich das Standard-VCL-Template geändert hat, Cookie-Handling für neue Personalisierungs-Features muss nachgezogen werden, und ein fehlerhaftes Purge-Pattern kann dazu führen, dass veraltete Preise oder Lagerbestände tagelang ausgeliefert werden. Teams ohne dedizierte DevOps-Ressourcen fahren mit dem eingebauten Cache oft besser, selbst wenn die Infrastruktur technisch Varnish erlauben würde.
5. VCL-Anpassungen speziell für Magento
Das von Magento generierte Standard-VCL deckt die Grundfunktionen ab, muss aber für reale Shops fast immer angepasst werden. Der wichtigste Anpassungsbereich ist das Cookie-Handling für eingeloggte Kunden. Magento setzt beim Login Cookies wie PHPSESSID und personalisierte Marker, die signalisieren, dass eine Antwort kundenspezifische Inhalte enthält und nicht aus dem gemeinsamen Cache bedient werden darf. Fehlt diese Logik in der VCL, landet im schlimmsten Fall der Warenkorb oder die Begrüßung eines Kunden im Cache eines anderen Besuchers, ein schwerwiegender Datenschutzfehler.
Für personalisierte Blöcke wie Mini-Cart, Kundenbegrüßung oder Empfehlungen setzt Magento auf Edge Side Includes. Der Hauptseiten-HTML-Rumpf bleibt vollständig cachebar, während einzelne Platzhalter über esi:include-Tags erst bei der Auslieferung durch Varnish mit aktuellem, nicht gecachtem Inhalt gefüllt werden. Damit lässt sich ein Shop mit personalisierten Elementen trotzdem zu einem hohen Prozentsatz aus dem Cache bedienen, statt bei jeder Anfrage die komplette Seite neu zu rendern.
Diese Kombination aus Cookie-basiertem Bypass und ESI-basierter Teilauslieferung ist der Kern dessen, was Varnish im Magento-Kontext so leistungsfähig macht, aber auch der Teil der Konfiguration, der am meisten Sorgfalt bei Updates verlangt.
sub vcl_recv {
# Bypass cache entirely for logged-in customers and active checkout
if (req.http.Cookie ~ "X-Magento-Vary=") {
return (pass);
}
# Strip tracking cookies that would otherwise fragment the cache
if (req.http.Cookie) {
set req.http.Cookie = regsuball(
req.http.Cookie,
"(^|; )(_ga|_gid|_fbp)=[^;]+",
""
);
if (req.http.Cookie == "") {
unset req.http.Cookie;
}
}
return (hash);
}
sub vcl_backend_response {
# Enable ESI processing for personalized fragments (mini cart, greeting)
if (bereq.url !~ "\.(css|js|png|jpg|svg|woff2?)$") {
set beresp.do_esi = true;
}
return (deliver);
}
6. Cache-Invalidierung und Purge-Strategien im Vergleich
Beide Ansätze nutzen dieselbe logische Grundlage: Tag-basierte Invalidierung. Jede gecachte Antwort wird beim Erzeugen mit Tags versehen, etwa der Produkt-ID, der Kategorie-ID oder dem Block-Namen. Ändert sich eine Entität, werden alle Cache-Einträge mit dem passenden Tag ungültig gemacht, ohne den gesamten Cache zu leeren. Der Unterschied liegt in der Ausführung: Der eingebaute Cache invalidiert Einträge direkt im PHP-Prozess über die konfigurierten Cache-Frontends, während bei aktivem Varnish zusätzlich ein HTTP-PURGE-Request an den Reverse-Proxy geschickt werden muss, damit auch dessen Speicher synchron bleibt.
Aus Entwicklersicht ist das dank Magentos Service Contracts weitgehend transparent. Ob im Hintergrund der eingebaute Cache-Storage bereinigt wird oder zusätzlich ein PURGE an Varnish geht, entscheidet Magento anhand der http_cache_hosts-Konfiguration automatisch. Eigener Code muss lediglich die Standard-Invalidierungs-APIs aufrufen und sich nicht darum kümmern, welche Cache-Ebene tatsächlich aktiv ist.
Für eigene Module oder gezielte Cache-Bereinigung nach Custom-Events lohnt sich ein eigener Purge-Service, der die vorhandenen Interfaces kapselt, statt Tags verstreut im Code zu invalidieren.
<?php
declare(strict_types=1);
namespace Mironsoft\CacheTools\Service;
use Magento\Framework\App\Cache\TypeListInterface;
use Magento\PageCache\Model\Cache\Type as FullPageCache;
/**
* Purges full page cache entries by tag.
* Works identically whether the built-in cache backend or a
* Varnish frontend is configured via http_cache_hosts.
*/
class CachePurger
{
/**
* @param TypeListInterface $cacheTypeList
* @param FullPageCache $fullPageCache
*/
public function __construct(
private readonly TypeListInterface $cacheTypeList,
private readonly FullPageCache $fullPageCache
) {
}
/**
* Invalidates all cache entries matching the given tags.
*
* @param array $tags
* @return void
*/
public function purgeByTags(array $tags): void
{
$this->fullPageCache->clean(
\Zend_Cache::CLEANING_MODE_MATCHING_ANY_TAG,
$tags
);
$this->cacheTypeList->invalidate(FullPageCache::TYPE_IDENTIFIER);
}
}
7. Monitoring und Debugging
Die Cache-Hit-Ratio ist die zentrale Kennzahl, um zu beurteilen, ob eine Cache-Ebene ihren Zweck erfüllt, unabhängig davon, ob der eingebaute Cache oder Varnish aktiv ist. Der einfachste Einstieg ist die Analyse des X-Magento-Cache-Debug-Headers per curl: Ein erster Request sollte MISS liefern, ein zweiter direkt danach HIT. Bleibt der zweite Request ebenfalls auf MISS, liegt entweder ein Konfigurationsfehler vor, oder Cookies verhindern, dass die Antwort überhaupt cachebar ist.
Bei Varnish liefert varnishstat zusätzlich aggregierte Kennzahlen zur Hit-Ratio seit dem letzten Neustart des Dienstes, und varnishlog erlaubt es, einzelne Requests live mitzuverfolgen, etwa um zu prüfen, ob PURGE-Requests tatsächlich ankommen und mit dem erwarteten Tag-Pattern verarbeitet werden. Der eingebaute Cache bietet kein äquivalentes Live-Tooling, hier bleiben Server-Logs und der Debug-Header die wichtigsten Werkzeuge.
Wichtig für belastbare Messungen: Immer mit denselben Request-Headern und ohne Cookies testen, da sowohl der eingebaute Cache als auch Varnish je nach Vary-Konfiguration unterschiedliche Cache-Einträge für unterschiedliche Cookie- oder Header-Kombinationen anlegen.
# Check cache debug header for a given URL (works for built-in cache and Varnish)
curl -sI https://shop.example.com/ | grep -i "X-Magento-Cache-Debug\|Age\|Cache-Control"
# Second request right after should show HIT if the cache is warm
curl -sI https://shop.example.com/ | grep -i "X-Magento-Cache-Debug"
# Varnish only: overall hit ratio since last service restart
varnishstat -1 | grep -E "cache_hit|cache_miss"
# Varnish only: live request log, filtered to PURGE calls
varnishlog -q "ReqMethod eq \"PURGE\""
# Compare TTFB with and without a warm cache
curl -o /dev/null -s -w "TTFB: %{time_starttransfer}s\n" https://shop.example.com/
8. Migration zwischen eingebautem Cache und Varnish
Der Weg vom eingebauten Cache zu Varnish ist technisch überschaubar: Varnish installieren, VCL über bin/magento varnish:vcl:generate erzeugen, den Webserver so umkonfigurieren, dass Varnish den öffentlichen Port übernimmt und Nginx oder Apache dahinter auf einem internen Port lauscht, und schließlich http_cache_hosts in env.php setzen. Der eigentliche Aufwand liegt nicht in dieser Grundinstallation, sondern in der Anpassung der VCL an projektspezifische Personalisierung, Cookie-Handling und ESI-Konfiguration, die im Standard-Template nicht abgebildet sind.
Typische Stolpersteine bei der Umstellung: SSL-Terminierung wird oft übersehen, weil Varnish selbst kein TLS spricht und ein vorgeschalteter Terminator wie Nginx oder ein Loadbalancer nötig ist. Ein zweiter häufiger Fehler ist, dass Health-Checks oder Monitoring-Tools weiterhin direkt den Applikationsserver statt Varnish ansprechen und dadurch verzerrte Messwerte liefern. Ein dritter Klassiker: Nach einem Magento-Upgrade ändert sich das Standard-VCL-Template, die projektspezifischen Anpassungen werden aber nicht nachgezogen, wodurch neue Cache-Tags oder geänderte Purge-Logik ins Leere laufen.
Der umgekehrte Weg, von Varnish zurück zum eingebauten Cache, wird seltener gegangen, kommt aber vor, etwa bei einem Wechsel auf Managed-Hosting ohne Reverse-Proxy-Unterstützung. Hier ist entscheidend, http_cache_hosts in env.php vollständig zu leeren und den Cache-Type full_page neu zu konfigurieren, da Magento sonst weiterhin versucht, PURGE-Requests an einen nicht mehr existierenden Varnish-Host zu senden.
9. Varnish vs. eingebauter Cache im direkten Vergleich
Die folgende Übersicht fasst die zentralen Entscheidungskriterien zusammen, an denen sich in der Praxis zeigt, ob der eingebaute Cache ausreicht oder Varnish FPC den zusätzlichen Betriebsaufwand rechtfertigt.
| Kriterium | Eingebauter Cache | Varnish FPC | Empfehlung |
|---|---|---|---|
| TTFB / Performance | PHP-Bootstrap bei jedem Request, auch bei Cache-Hit | Antwort ohne PHP-Beteiligung | Varnish ab hohem Traffic |
| Hosting-Anforderungen | Läuft ohne root, geeignet für Shared Hosting | Benötigt dedizierten Port und root-Zugriff | Nach Hosting-Typ entscheiden |
| Betriebsaufwand | Kein separater Dienst zu pflegen | Eigene VCL-Pflege bei jedem Upgrade nötig | Team-Kompetenz vorher prüfen |
| Invalidierung | Direkt im PHP-Prozess | Sofortiges HTTP-PURGE ohne PHP | Varnish bei hoher Schreiblast |
| Skalierung | An PHP-FPM-Kapazität gebunden | Horizontal unabhängig vom Backend skalierbar | Varnish für Wachstumsprognosen |
Kein Kriterium allein entscheidet. Ein Shop mit moderatem Traffic auf Managed-Hosting profitiert selten spürbar von Varnish, während ein wachsender Shop mit dediziertem Server und klaren TTFB-Zielen den zusätzlichen Betriebsaufwand meist schnell wieder hereinholt.
10. Zusammenfassung
Die Entscheidung zwischen Varnish und dem eingebauten Full Page Cache in Magento 2 ist keine Glaubensfrage, sondern eine Frage von Traffic-Profil, Hosting-Setup und verfügbarer Team-Kompetenz. Der eingebaute Cache erledigt seinen Job zuverlässig für kleine bis mittlere Shops, ohne zusätzliche Infrastruktur und ohne VCL-Pflege, stößt aber bei hohem Traffic an die Grenze des PHP-Bootstrap-Overheads. Varnish FPC eliminiert genau diesen Overhead, verlangt im Gegenzug aber dediziertes Hosting, saubere Cookie- und ESI-Konfiguration sowie kontinuierliche Pflege der VCL bei jedem Magento-Upgrade.
Wer die Entscheidung anhand der in diesem Beitrag beschriebenen Kriterien trifft, statt Varnish reflexhaft, weil angeblich Best Practice, einzusetzen, vermeidet sowohl unnötigen Betriebsaufwand als auch echte Performance-Engpässe. Monitoring über den Cache-Debug-Header und, bei aktivem Varnish, über varnishstat zeigt frühzeitig, ob die gewählte Cache-Ebene tatsächlich die erwartete Wirkung erzielt.
Varnish vs. eingebauter Cache in Magento 2, das Wichtigste auf einen Blick
Eingebauter Cache
Kein zusätzlicher Dienst, läuft auf jedem Hosting-Setup, ideal für kleine bis mittlere Shops ohne root-Zugriff.
Varnish FPC
Beantwortet gecachte Requests ohne PHP-Beteiligung, verlangt dediziertes Hosting und laufende VCL-Pflege.
Purge-Strategie
Tag-basierte Invalidierung in beiden Fällen, bei Varnish zusätzlich über HTTP-PURGE-Requests.
Monitoring
X-Magento-Cache-Debug-Header für beide Varianten, varnishstat und varnishlog zusätzlich bei Varnish.
11. FAQ: Varnish vs. eingebauter Cache in Magento 2
1Was ist der Unterschied zwischen eingebautem Cache und Varnish?
2Brauche ich für einen kleinen Shop Varnish?
3Was bedeutet X-Magento-Cache-Debug?
4Wie funktioniert der Purge-Flow?
5Eingebauten Cache und Varnish gleichzeitig nutzen?
6Was ist ESI und wozu dient es?
7Wie messe ich die Cache-Hit-Ratio?
8Stolpersteine bei der Migration zu Varnish?
9Funktioniert Varnish auf Shared Hosting?
10VCL nach Upgrade nicht aktualisiert?
Mironsoft
Magento-2-Performance, Caching-Architektur und Hosting-Beratung
Varnish oder eingebauter Cache, die richtige Entscheidung für euren Shop?
Wir analysieren Traffic-Profil, Hosting-Setup und bestehende Cache-Konfiguration und implementieren die passende Lösung, von VCL-Tuning bis zur sauberen Cache-Invalidierungsstrategie.
Cache-Audit
Analyse von Hit-Ratio, TTFB und bestehender VCL- oder Cache-Konfiguration
Varnish-Setup
VCL-Anpassung für Cookie-Handling, ESI und tag-basierte Purge-Strategien
Monitoring
Cache-Hit-Ratio-Dashboards und Alerting für Purge-Fehler