Der HTTP Cache in Shopware 6 ist ein mächtiges Werkzeug, um die Ladezeiten zu verbessern und die Serverlast zu verringern. Durch das Zwischenspeichern von Inhalten kann der Cache sicherstellen, dass wiederkehrende Anfragen schneller bedient werden. Doch trotz dieser Vorteile gibt es einige Bereiche, in denen wir den Shopware 6 Cache optimieren können.
In diesem Beitrag werde ich auf Optimierungsmöglichkeiten eingehen, die dabei helfen, den Cache effizienter zu gestalten und die Performance Deines Shops weiter zu steigern. Von einer genaueren Konfiguration der Cache-Strategien bis hin zur Implementierung zusätzlicher Techniken – hier erfährst Du, wie Du Deinen Shopware 6 Cache perfekt auf die Anforderungen Deines Shops abstimmen kannst.
In meinem letzten Beitrag habe ich erklärt, welche verschiedenen Caching-Mechanismen es gibt und wie sie bei Shopware funktionieren. Solltest Du den Beitrag noch nicht gesehen haben, kannst Du die Infos hier nachlesen.
Grundlegende Caching-Checks
Bevor wir uns an die Optimierung des HTTP Caches in Shopware 6 machen, sollten wir sicherstellen, dass der Cache überhaupt aktiviert ist und der Shop im Produktivmodus läuft. Das klingt erstmal basic, aber diese beiden Einstellungen sind essenziell, damit der Cache überhaupt greift und seine volle Wirkung entfalten kann.
Um das zu prüfen, öffne die .env
-Datei im Stammverzeichnis Deiner Shopware-Installation. Dort findest Du die folgenden Einstellungen:
- Produktivmodus aktivieren: Stelle sicher, dass
APP_ENV
in Deiner .env-Datei aufprod
steht. Im dev-Modus (oder auch im Wartungsmodus) wird der Cache direkt umgangen. - HTTP Cache aktivieren: Prüfe, ob in Deiner .env die Variable “SHOPWARE_HTTP_CACHE_ENABLED” auf 1 steht und eine SHOPWARE_HTTP_DEFAULT_TTL konfiguriert ist.
Im Cache-Modul der Administration sieht man ebenfalls, ob der HTTP-Cache auch von Shopware als aktiv angenommen wird.
Caching für eingeloggte Kunden und Warenkorbinhalte
Im Standardverhalten von Shopware 6 wird der HTTP Cache für eingeloggte Kunden und Kunden mit Artikeln im Warenkorb komplett umgangen. Das bedeutet, dass der CacheStore::lookup
in diesen Fällen immer null
zurückgibt – gecachte Inhalte werden somit nie ausgegeben. Diese Feature ist zwar hilfreich, um personalisierte Inhalte anzuzeigen, kann aber auch zu unnötig langen Ladezeiten & Belastung des Servers führen.
Es lohnt daher sich, zu prüfen, ob dieses Verhalten für Deinen Shop überhaupt sinnvoll ist. Besonders der Warenkorb (Cart) muss in vielen Fällen nicht zwingend als individueller „State“ betrachtet werden und könnte von der Cache-Invalidierung ausgeschlossen werden. Auf diese Weise könnte man zumindest für Kunden mit Artikeln im Warenkorb ebenfalls gecachte Inhalte nutzen und somit die Performance steigern. Der State für die config heißt “cart-filled”
Bei eingeloggten Kunden hängt es stark von den Anforderungen ab. Wenn keine kundenindividuellen Inhalte wie Preise benutzt werden, können wir den State auch einfach entfernen. Wenn aber Preis-Rules mit unterschiedlichen Kundengruppen verwendet werden, muss die Invalidierung hier aktiv bleiben. Man könnte als etwas komplexere Lösung die Kundengruppe als Bestandteil des Cache Keys festlegen und den Cache dennoch aktiv lassen. Damit würden gecachte Seiten für verschiedene Kundengruppen genutzt und gleichzeitig der Personalisierungsbedarf berücksichtigt. Der State für die config heißt “logged-in”
Je nachdem, welcher Fall für Euch wichtig ist, könnt ihr in der Shopware Konfiguration die für Euch wichtigen States hinterlegen. Im Idealfall klammern wir beide Fälle aus und geben nur ein leeres Array an:
# config/packages/prod/shopware.yaml
shopware:
cache:
invalidation:
http_cache: []
Wenn wir den Cache nur bei eingeloggten Kunden umgehen wollen, wäre diese Config passen:
# config/packages/prod/shopware.yaml
shopware:
cache:
invalidation:
http_cache: ['logged-in']
Automatische Cache-Invalidierung durch ERP/ PIM
Wenn wir das automatische Umgehen des Caches abgestimmt haben, schauen wir uns als nächstes an, wie oft der Cache durch z.B. ERP-API-Calls automatisch invalidiert wird.
In Shopware 6 werden beim Speichern von Änderungen automatisch bestimmte Cache-Tags und damit gecachte Inhalte geleert, um die neuen Werte auch im Shop verfügbar zu machen. Ein häufiges Beispiel ist die automatische Invalidierung bei einer Preisänderung: Sobald ein Produktpreis aktualisiert wird, sorgt Shopware dafür, dass alle Seiten, die dieses Produkt anzeigen, aus dem Cache geleert werden. Dies verhindert, dass der gesamte Cache neu aufgebaut werden muss und sorgt für eine effiziente Aktualisierung.
Das System nutzt hierfür den CacheInvalidationSubscriber
, der auf Events wie den ProductIndexerEvent
reagiert, um gezielt Listings, Detailseiten und gecachte Routen über den HTTP-Cache und den Object Cache zu invalidieren. Dieser gezielte Ansatz stellt sicher, dass nur die betroffenen Seiten neu generiert werden, was die Performance deutlich verbessert.
Cache-Hit-Rate optimieren
Für eine langfristige Optimierung der Cache-Strategie lohnt es sich, die Cache-Hit-Rate zu beobachten. Tools wie Tideways ermöglichen es, die Hit Rate und das Invalidierungsverhalten über einen längeren Zeitraum zu messen. Ein ineffizienter API-Zugriff oder eine schlecht umgesetzte API-Anbindung kann jedoch dazu führen, dass der Cache häufiger invalidiert wird, als tatsächlich notwendig ist. Das Resultat: eine kleine Cache-Hit-Rate, damit sehr viele ungecachte Seitenaufrufe und lange Ladezeiten.
Bei einem unserer Kunden konnten wir genau ein solches Problem feststellen. Stock-Änderungen haben die Listing-Seiten ständig invalidiert, obwohl die Information dort nicht benötigt wurde. Über eine Anpassung des Verhaltens konnten wir die automatische Invalidierung umgehen, die Cache-Hit-Rate und damit die Ladezeiten im Listing erhöhen.
Verzögerte Cache-Invalidierung
Eine weitere Möglichkeit zur Verbesserung der Cache-Performance in Shopware 6 bietet die verzögerte Cache-Invalidierung. Dabei werden Invalidierungs-Events nicht sofort ausgeführt, sondern gesammelt und gebündelt verarbeitet. Dies lässt sich durch das Setzen der Option shopware.cache.invalidation.delay
auf 1
aktivieren. Zusätzlich wird delay_options.storage
auf Redis gesetzt, und als dsn
kann eine Redis-Verbindung angegeben werden – oft die gleiche, die auch für Sessions genutzt wird, da alle Informationen in einem Schlüssel gespeichert werden.
Mit dieser Einstellung landen alle durch API-Calls oder andere automatisierte Prozesse ausgelösten Cache-Invalidierungen zunächst in Redis, statt sofort im Cache gelöscht zu werden. Ein Cronjob, der standardmäßig alle 20 Sekunden ausgeführt wird, lädt dann alle in Redis gesammelten Tags und führt die Invalidierungen gebündelt aus. So kann man bei häufigen Änderungen eine deutliche Reduzierung der unnötigen Invalidierungen erreichen. Falls gewünscht, lässt sich der Cronjob-Intervall auch verlängern, um die Cache-Hit-Rate und damit die Ladezeiten des Shops weiter zu optimieren.
Die verzögerte Invalidierung hat jedoch auch potenzielle Nachteile. Wenn der Cache z. B. nur alle zwei Stunden geleert wird, kann es passieren, dass eine große Menge an Seiten ohne Cache geladen werden muss. Dies kann zu einer erhöhten Serverauslastung führen, wenn die Besucher gleichzeitig auf viele ungesehene Seiten zugreifen. Daher ist es wichtig, die Verzögerungseinstellungen gut auf den spezifischen Bedarf abzustimmen, um die Vorteile ohne negative Auswirkungen auf die Performance zu nutzen.
Eine Konfiguration in den Config-Files kann z.B. folgendermaßen aussehen:
# config/packages/prod/shopware.yaml
shopware:
cache:
invalidation:
delay: 1
delay_options:
storage: redis
dsn: 'redis://127.0.0.1:6379'
Cache-ID in der .env setzen
Für die Caching-Prozesse nutzt Shopware eine spezielle Cache-ID, die in der Datenbank gespeichert wird und sich normalerweise nicht ändert. Bei der Einrichtung des Shops wird eine zufällige Hexadezimalzahl generiert und als Cache-ID in einem bestimmten Datenbankfeld hinterlegt. Bei jedem Seitenaufruf greift Shopware auf dieses Feld zu und lädt die Cache-ID aus der Datenbank.
Obwohl es sich dabei um eine kleine Abfrage handelt, kann diese dennoch optimiert werden, indem die Cache-ID direkt in der .env
-Datei definiert wird. Durch das Setzen der Cache-ID in der .env
sparst Du Dir die Datenbankabfrage bei jedem Request, was besonders bei hoch frequentierten Seiten die Performance minimal, aber konstant verbessert.
Die ID findest du in der Datenbank-Tabelle “app_config”. Hier ist ein Eintrag mit dem key “cache-id”. Die Anpassung ist einfach: Setze die Cache-ID direkt in der .env
, z. B.:
# .env
SHOPWARE_CACHE_ID=deine_cache_id
Diese kleine Optimierung reduziert die Last auf die Datenbank und sorgt für eine effizientere Verarbeitung der Anfragen, was sich insbesondere bei hoher Zugriffszahl positiv bemerkbar machen kann.
Granulares Caching deaktivieren
Shopware verfügt über ein feingranulares Caching-System für Systemkonfigurationen, Übersetzungen und Theme-Einstellungen. Dadurch können bei Änderungen an z.B. einer Theme-Konfiguration alle Seiten, die diese Konfiguration nutzen, geleert werden.
Um das zu gewährleisten, muss allerdings pro config ein eigener Tag zur Response hinzugefügt werden, was gerade bei Redis oder Varnish zu sehr vielen Keys führen kann.
Um den Overhead allgemein zu vermeiden, lohnt es sich, das Verhalten zu deaktivieren:
# config/packages/shopware.yaml
shopware:
cache:
tagging:
each_config: false
each_snippet: false
each_theme_config: false
Cache compression mit zstd
Wie wir im letzten Beitrag gelernt haben, komprimiert Shopware Inhalte, bevor sie im Cache gespeichert werden. Das gilt sowohl für den HTTP-Cache als auch andere Pools, wie z.B. den object-Cache. Für die Komprimierung wird die Klasse CacheValueCompressor verwendet.
Das Komprimieren reduziert die Speichernutzung und ist besonders nützlich, wenn z.B. Redis als Cache-Backend eingesetzt wird, da Redis im Arbeitsspeicher liegt und dieser Speicher kostspielig ist.
Shopware Standard: gzip
Shopware nutzt standardmäßig die Gzip-Komprimierung (gzcompress
und gzuncompress
), um die Cache-Inhalte zu verkleinern. Gzip ist weit verbreitet und effektiv, hat jedoch Grenzen. Bei Seiten mit besonders viel Content oder bei sehr großen Datenobjekten kann die Komprimierung und Dekomprimierung viel Zeit beanspruchen. Dies führt mitunter zu längeren Ladezeiten – auch bei eigentlich gecachten Inhalten, die zur schnellen Bereitstellung gedacht sind.
Ab Shopware 6.6 kann man über eine einfache Konfiguration eine alternative Komprimierung verwenden, um die Ladezeit entsprechend zu beschleunigen: Zstandard (zstd). Mit dieser Methode lassen sich Inhalte schneller und effizienter komprimieren, was speziell bei großen Datenmengen zu spürbaren Performance-Gewinnen führen kann. Über einen Patch kann zstd sogar in früheren Shopware-Versionen integriert werden.
Vorbereitung für zstd
Um Zstandard nutzen zu können, muss zunächst die zstd PHP-Erweiterung auf dem Server installiert und aktiviert sein. Hierzu empfiehlt es sich, Rücksprache mit dem Hosting-Anbieter zu halten, damit die Erweiterung ordnungsgemäß eingerichtet wird. Ob zstd verfügbar ist, kann man z.B. über die phpinfo sehen:
Sobald zstd verfügbar ist, kann die Komprimierungsmethode in einer Konfig-Datei einfach umgestellt werden:
# config/packages/prod/shopware.yaml
shopware:
cache:
cache_compression: true
cache_compression_method: 'zstd'
Diese Umstellung könnte auch für den Warenkorb-Cache vorgenommen werden, um Ladezeiten weiter zu optimieren.
# config/packages/prod/shopware.yaml
shopware:
cart:
compress: true
compression_method: zstd
Abschließend muss der Cache vollständig geleert werden.
Performance-Gewinne durch zstd
Durch die Umstellung auf zstd konnte ich in Projekten bereits deutliche Verbesserungen der Ladezeit feststellen. Je nach Seitenstruktur und Datenvolumen waren Reduzierungen von 1-2 Sekunden möglich. Im Durchschnitt sinkt die Ladezeit jedoch eher um etwa 500 ms, was trotzdem eine erhebliche Verbesserung darstellt.
Mögliche Herausforderungen
Es gibt einige Punkte, die bei der Aktivierung von zstd beachtet werden sollten:
- Cache leeren nach Umstellung: Nach der Umstellung der Cache-Komprimierungsmethode kann es zu Fehlermeldungen kommen. Daher sollte der Cache nach dem Wechsel vollständig geleert werden. Ggf. muss auch der OPcache geleert werden.
- Probleme bei der Synchronisierung auf Staging-Systeme: Wenn zstd auf einem System aktiviert ist, sollte die Komprimierungsmethode beim Klonen auf Staging- oder lokale Umgebungen beachtet werden. Falls dort die zstd PHP-Erweiterung fehlt, kann dies zu Problemen führen. Um dies zu umgehen, sollte entweder die Config-Datei beim Klonen ignoriert werden oder die Erweiterung auch auf den anderen Systemen verfügbar sein.
TL;DR
Hier eine kurze Zusammenfassung aller relevanten Themen:
- je nach Möglichkeit Invalidierung für logged-in & cart deaktivieren
- Cache-Hit-Rate der wichtigsten Seiten prüfen und ggf. Maßnahmen umsetzten
- Cache-Invalidation-Delay konfigurieren
- Cache-ID in der .env setzten
- Granulares Caching deaktivieren
- zstd für CacheCompression verwenden
Fazit
Die vielfältigen Optimierungsmöglichkeiten im Shopware 6 Cache bieten einen großen Spielraum, um die Performance und Stabilität eines Shops gezielt zu verbessern. Durch Anpassungen das Setzen der Cache-ID in der .env
-Datei lassen sich unnötige Datenbankabfragen und Overhead reduzieren. Gleichzeitig helfen Maßnahmen wie die verzögerte Cache-Invalidierung und die Wahl einer effizienten Komprimierungsmethode wie Zstandard (zstd), den Cache-Ressourcenverbrauch zu minimieren und die Ladezeiten zu verkürzen.
Jede dieser Optimierungen adressiert spezifische Herausforderungen – von der Reduzierung des Speicherbedarfs bei Redis- oder Varnish-Caches bis hin zur Verbesserung der Cache-Hit-Rate durch gezieltes Invalidieren von Inhalten. Besonders in Shops mit hohem Traffic oder umfangreichem Content können diese Maßnahmen zu spürbaren Verbesserungen führen, indem sie die Ressourcen des Servers entlasten und die User Experience insgesamt verbessern.
Letztlich erfordert die Wahl der besten Caching-Strategie immer eine individuelle Anpassung an die Bedürfnisse und das technische Setup des Shops. Mit den beschriebenen Optimierungen lassen sich gezielt Ladezeiten senken und die Effizienz steigern – ein klarer Gewinn für jeden Shopware-Shop, der auf Performance und Kundenzufriedenheit setzt.