Caching-Strategien: Varnish, Redis und Browser-Cache
Caching ist der wirkungsvollste Hebel für schnelle Server-Antwortzeiten. Eine durchdachte Caching-Architektur reduziert die Time to First Byte (TTFB) von Hunderten von Millisekunden auf unter 10 Millisekunden, senkt die Serverlast um 80 bis 95 Prozent und macht Websites auch bei hohem Traffic stabil und responsiv. Trotzdem setzen viele Websites Caching nur oberflächlich ein – ein Browser-Cache-Header hier, ein CDN dort – ohne die verschiedenen Caching-Schichten aufeinander abzustimmen. Das Ergebnis sind Cache-Misses, veraltete Inhalte und verschenktes Performance-Potenzial. Dieser Artikel zeigt, wie Varnish als HTTP-Accelerator, Redis als Applikations-Cache und Browser-Caching zusammen eine mehrstufige Architektur bilden, die Antwortzeiten unter 100 Millisekunden ermöglicht.
Warum mehrstufiges Caching den Unterschied macht
Jeder HTTP-Request durchläuft auf dem Weg zum Server mehrere Stationen: DNS-Auflösung, TCP-Verbindungsaufbau, TLS-Handshake, Weiterleitung durch Load Balancer und Reverse Proxy, Verarbeitung durch den Applikationsserver, Datenbankabfragen und schließlich das Rendering der Antwort. Ohne Caching dauert dieser Prozess für eine dynamische Seite typischerweise 200 bis 800 Millisekunden. Laut Google sollte die TTFB einer Website unter 800 Millisekunden liegen, wobei Werte unter 200 Millisekunden als gut gelten (Quelle: Google, 2024).
Mehrstufiges Caching setzt an verschiedenen Stellen dieser Kette an: Der Browser-Cache verhindert, dass bekannte Ressourcen überhaupt erneut angefordert werden. Das CDN speichert Kopien auf Edge-Servern nahe am Nutzer und eliminiert die Netzwerklatenz zum Origin-Server. Varnish als HTTP-Accelerator liefert gecachte Seiten in 1 bis 5 Millisekunden aus dem Arbeitsspeicher, ohne den Applikationsserver zu belasten. Redis beschleunigt die Applikation selbst, indem Datenbankabfragen, Sessionen und berechnete Ergebnisse im RAM gespeichert werden.
Die Stärke einer mehrstufigen Architektur liegt in der Redundanz: Selbst wenn eine Schicht keinen Cache Hit erzielt, greift die nächste. Bei einer typischen Website mit 95 Prozent Varnish-Hit-Rate erreichen nur 5 Prozent der Requests den Applikationsserver – und dort beschleunigt Redis die Verarbeitung um weitere 60 bis 80 Prozent. Das Ergebnis ist eine konsistent schnelle Website, die auch bei Lastspitzen stabil bleibt.
Varnish Cache: HTTP-Beschleunigung auf der Überholspur
Varnish ist ein HTTP-Accelerator, der als Reverse Proxy vor dem Webserver sitzt und HTTP-Antworten im Arbeitsspeicher zwischenspeichert. Bei einem Cache Hit liefert Varnish die gespeicherte Antwort direkt aus, ohne den dahinterliegenden Webserver oder Applikationsserver zu kontaktieren. Die Antwortzeit bei einem Cache Hit liegt typischerweise bei 1 bis 5 Millisekunden – verglichen mit 200 bis 500 Millisekunden für eine dynamisch generierte Seite. Laut W3Techs wird Varnish von 2,3 Prozent aller Websites eingesetzt, darunter Wikipedia, The Guardian und viele hochfrequentierte E-Commerce-Plattformen (Quelle: W3Techs, 2025).
Die Konfiguration von Varnish erfolgt über die Varnish Configuration Language (VCL), eine domänenspezifische Sprache, die präzise Kontrolle über das Caching-Verhalten ermöglicht. VCL definiert, welche Requests gecacht werden, wie lange Cache-Einträge gültig sind, wie mit Cookies umgegangen wird und unter welchen Bedingungen der Cache invalidiert wird. Die Flexibilität von VCL ist gleichzeitig Stärke und Herausforderung: Eine falsch konfigurierte VCL kann dazu führen, dass entweder zu wenig gecacht wird (niedrige Hit Rate) oder personalisierte Inhalte an falsche Nutzer ausgeliefert werden.
Für Content-Websites und Blogs ist die VCL-Konfiguration vergleichsweise einfach: Alle GET-Requests ohne Session-Cookie werden gecacht, POST-Requests und Seiten mit Set-Cookie-Header werden durchgereicht. Für Shopware-basierte Shops und andere E-Commerce-Systeme wird die Konfiguration komplexer, da zwischen öffentlichen Seiten (Kategorien, Produktdetails für nicht eingeloggte Nutzer), teilweise personalisierten Seiten (Warenkorb-Icon, Mini-Cart) und vollständig personalisierten Seiten (Checkout, Kundenkonto) unterschieden werden muss.
Grace Mode
Liefert abgelaufene Cache-Einträge aus, während im Hintergrund eine frische Version geholt wird. Verhindert Wartezeiten bei Cache-Misses und schützt den Backend bei Lastspitzen.
Cache Tags
Ermöglicht gezielte Invalidierung einzelner Ressourcen statt kompletter Cache-Löschung. Bei einer Produktänderung werden nur die betroffenen Seiten invalidiert.
Edge Side Includes
ESI teilt Seiten in cachbare und dynamische Fragmente auf. Der Seitenrahmen wird gecacht, personalisierte Elemente wie der Warenkorb werden pro Request eingefügt.
Redis: Der Applikations-Cache für Datenbank und Session
Redis (Remote Dictionary Server) ist ein In-Memory-Datenspeicher, der als Applikations-Cache zwischen Anwendungslogik und Datenbank sitzt. Im Gegensatz zu Varnish, der komplette HTTP-Antworten speichert, cached Redis einzelne Datenfragmente: Ergebnisse von Datenbankabfragen, Sessionen, berechnete Werte und serialisierte Objekte. Die Zugriffszeit liegt bei 0,1 bis 0,5 Millisekunden – Hunderte Male schneller als eine Datenbankabfrage, die typischerweise 5 bis 50 Millisekunden dauert.
Die wichtigste Einsatzform von Redis in Web-Anwendungen ist der Session-Cache. Standardmäßig speichern PHP-Anwendungen Sessions als Dateien auf der Festplatte, was bei vielen gleichzeitigen Nutzern zu I/O-Engpässen führt und in Cluster-Umgebungen mit mehreren Applikationsservern nicht skaliert. Redis löst beide Probleme: Sessions werden im RAM gespeichert (schnell) und sind von allen Applikationsservern aus erreichbar (skalierbar). Für eine professionelle Server-Infrastruktur ist Redis als Session-Handler Standard.
Der Object-Cache speichert die Ergebnisse aufwändiger Berechnungen und Datenbankabfragen. Statt bei jedem Seitenaufruf dieselbe Datenbankabfrage auszuführen – etwa die Kategorie-Hierarchie, die Navigationsstruktur oder die Konfigurationswerte – wird das Ergebnis einmal berechnet und in Redis gespeichert. Nachfolgende Requests lesen das Ergebnis aus Redis in unter einer Millisekunde. Diese Technik ist besonders wirkungsvoll für Abfragen, die häufig ausgeführt werden und sich selten ändern – was auf die Mehrheit der Konfigurationsabfragen zutrifft.
Redis bietet darüber hinaus spezialisierte Datenstrukturen, die über einfaches Key-Value-Caching hinausgehen: Sorted Sets für Echtzeit-Leaderboards und Ranglisten, Pub/Sub für die Kommunikation zwischen Applikationsservern bei Cache-Invalidierung, Streams für Event-Sourcing und Message-Queue-Funktionalität und Lua-Scripting für atomare, servereitige Operationen. Diese Vielseitigkeit macht Redis zu einem zentralen Infrastrukturbaustein, der weit über reines Caching hinausgeht.
Browser-Cache: Die erste und schnellste Caching-Schicht
Der Browser-Cache ist die schnellste Caching-Schicht, da er Ressourcen lokal auf dem Gerät des Nutzers speichert. Ein Cache Hit im Browser-Cache erfordert keinen Netzwerk-Request – die Ressource wird in Mikrosekunden aus dem lokalen Speicher geladen. Die korrekte Konfiguration der Browser-Cache-Header ist entscheidend für die Performance bei wiederholten Besuchen und beim Navigieren zwischen Seiten.
Die zwei wichtigsten HTTP-Header für das Browser-Caching sind Cache-Control und ETag. Cache-Control definiert, wie lange eine Ressource im Browser-Cache gültig ist und ob sie erneut validiert werden muss. Für statische Assets wie CSS, JavaScript und Bilder, die über Content-Hashing versioniert werden, empfehlen wir Cache-Control: public, max-age=31536000, immutable – das erlaubt dem Browser, die Ressource ein Jahr lang zu cachen, ohne sie jemals zu revalidieren. Bei Änderungen ändert sich der Dateiname (Hash), sodass automatisch die neue Version geladen wird.
Für HTML-Dokumente ist die Strategie anders: Cache-Control: public, max-age=0, must-revalidate in Kombination mit einem ETag oder Last-Modified-Header. Bei jedem Aufruf prüft der Browser beim Server, ob sich das Dokument geändert hat (Conditional Request). Hat es sich nicht geändert, antwortet der Server mit einem schlanken 304 Not Modified statt das gesamte Dokument erneut zu übertragen. Die Validierung selbst dauert nur wenige Millisekunden – deutlich weniger als das vollständige Laden des Dokuments.
Der stale-while-revalidate-Mechanismus kombiniert das Beste aus beiden Welten: Der Browser zeigt den gecachten Inhalt sofort an (keine Wartezeit) und aktualisiert ihn im Hintergrund. Cache-Control: public, max-age=3600, stale-while-revalidate=86400 bedeutet: Die Ressource gilt eine Stunde als frisch. Danach wird sie noch 24 Stunden aus dem Cache geliefert, während im Hintergrund eine frische Version geholt wird. Für Content-Websites ist dieses Pattern ideal, da Nutzer nie warten müssen und trotzdem immer relativ aktuelle Inhalte sehen.
CDN-Caching: Globale Auslieferung mit Edge-Nodes
Ein CDN (Content Delivery Network) speichert Kopien von Ressourcen auf Edge-Servern, die geografisch nahe am Nutzer stehen. Während die physische Entfernung zum Origin-Server Netzwerklatenz verursacht – typischerweise 50 bis 200 Millisekunden zwischen Kontinenten – liefert ein Edge-Server Inhalte mit einer Latenz von 5 bis 20 Millisekunden. Laut Akamai nutzen 68 Prozent der Top-1000-Websites ein CDN (Quelle: W3Techs, 2025).
Die CDN-Konfiguration für eine mehrstufige Caching-Architektur erfordert klare Regeln für das Zusammenspiel mit Varnish und dem Browser-Cache. Das CDN respektiert die Cache-Control-Header des Origin-Servers und speichert Ressourcen entsprechend. Für statische Assets mit langen Cache-Zeiten fungiert das CDN als globaler Verteiler. Für HTML-Dokumente, die über Varnish gecacht werden, agiert das CDN als zusätzliche Caching-Schicht mit eigenem TTL, das typischerweise kürzer ist als das Varnish-TTL.
Ein kritischer Aspekt ist die Cache-Invalidierung im CDN. Wenn sich Inhalte auf dem Origin-Server ändern, müssen die gecachten Kopien auf allen Edge-Servern aktualisiert werden. Die meisten CDN-Anbieter bieten eine Purge-API, über die einzelne URLs oder URL-Muster invalidiert werden können. Für Websites, die häufig aktualisiert werden, empfiehlt sich eine Kombination aus kurzen TTLs (5 bis 60 Minuten) und stale-while-revalidate, sodass Edge-Server abgelaufene Inhalte ausliefern, während sie im Hintergrund eine frische Version holen.
Cache-Invalidierung: Die schwierigste Aufgabe im Caching
Phil Karlton wird das berühmte Zitat zugeschrieben, dass es nur zwei schwierige Dinge in der Informatik gibt: Cache-Invalidierung und Namensgebung. Cache-Invalidierung ist deshalb so komplex, weil sie zwei widersprüchliche Ziele vereinen muss: Inhalte sollen so lange wie möglich gecacht werden (Performance), aber Änderungen sollen so schnell wie möglich sichtbar sein (Aktualität).
Die einfachste Invalidierungsstrategie ist zeitbasiert (TTL): Cache-Einträge werden nach einer definierten Lebensdauer automatisch ungültig. Diese Strategie ist einfach zu implementieren, hat aber den Nachteil, dass Änderungen erst nach Ablauf des TTL sichtbar werden. Für Inhalte, die sich selten ändern (Impressum, statische Seiten), sind TTLs von Stunden oder Tagen akzeptabel. Für häufig aktualisierte Inhalte (Produktpreise, Lagerverfügbarkeit) sind kurze TTLs von Minuten oder sogar Sekunden notwendig.
Die elegantere Lösung ist tag-basierte Invalidierung: Jeder Cache-Eintrag wird mit Tags versehen, die seine Abhängigkeiten beschreiben. Eine Produktseite erhält beispielsweise die Tags product-123, category-schuhe und brand-nike. Wenn sich das Produkt 123 ändert, werden alle Cache-Einträge mit dem Tag product-123 invalidiert – unabhängig davon, ob es sich um die Produktdetailseite, eine Kategorieliste oder einen Suchergebnis-Cache handelt. Varnish unterstützt tag-basierte Invalidierung nativ über xkey-VCL-Module.
Für Shopware-basierte Shops bietet das Framework eine integrierte Cache-Invalidierung über HTTP-Cache-Tags. Bei jeder Änderung an Produkten, Kategorien oder CMS-Seiten sendet Shopware automatisch Invalidierungs-Requests an den Reverse Proxy, der die betroffenen Cache-Einträge löscht. Diese Integration reduziert die Konfigurationsarbeit erheblich, erfordert aber eine korrekte Einrichtung der HTTP-Cache-Konfiguration und der Varnish-VCL.
| Strategie | Komplexität | Aktualität | Einsatzgebiet |
|---|---|---|---|
| TTL (zeitbasiert) | Niedrig | Verzögert (TTL-abhängig) | Statische Inhalte, Assets |
| Tag-basiert (xkey) | Mittel | Sofort nach Invalidierung | CMS-Seiten, Produktdaten |
| Purge-API (URL-basiert) | Niedrig | Sofort nach Purge | Einzelne Seiten, Notfall |
| Ban (Regex-basiert) | Hoch | Sofort (Lazy Evaluation) | Massenänderungen |
| stale-while-revalidate | Niedrig | Hintergrund-Update | Content-Websites, Blogs |
| Content-Hash (Immutable) | Niedrig | Sofort (neuer Hash) | CSS, JS, Bilder mit Hash |
Cache-Header-Strategie: Die richtigen Header für jeden Ressourcentyp
Eine konsistente Cache-Header-Strategie ist die Grundlage für effektives Caching auf allen Ebenen. Jeder Ressourcentyp erfordert unterschiedliche Cache-Header, die auf die jeweilige Änderungshäufigkeit und Sensibilität abgestimmt sind. Eine falsche Header-Konfiguration führt entweder zu häufigen unnötigen Revalidierungen (zu kurze TTLs) oder zu veralteten Inhalten bei den Nutzern (zu lange TTLs ohne Invalidierung).
Für statische Assets mit Content-Hashing (CSS, JavaScript, Bilder mit Hash im Dateinamen) empfehlen wir: Cache-Control: public, max-age=31536000, immutable. Da der Dateiname bei jeder Änderung wechselt, kann der Browser die Datei unbegrenzt cachen. Für HTML-Dokumente: Cache-Control: public, max-age=0, must-revalidate mit ETag-Header. Für API-Antworten mit personalisierten Daten: Cache-Control: private, no-store. Für semi-statische Inhalte wie Blog-Artikel: Cache-Control: public, max-age=3600, stale-while-revalidate=86400.
Der Vary-Header ist ein oft übersehener, aber kritischer Bestandteil der Cache-Strategie. Er teilt Caches (Browser, CDN, Varnish) mit, dass die Antwort von bestimmten Request-Headern abhängt. Vary: Accept-Encoding ist Standard und sorgt dafür, dass Brotli- und Gzip-komprimierte Versionen separat gecacht werden. Vary: Accept ermöglicht das Caching verschiedener Bildformate (WebP, AVIF) unter derselben URL. Aber Vorsicht: Jeder zusätzliche Vary-Header multipliziert die Anzahl der Cache-Einträge und kann die Hit Rate reduzieren.
Varnish VCL: Praxisbeispiele für typische Szenarien
Die VCL-Konfiguration entscheidet über die Effektivität des Varnish-Caches. Die vier wichtigsten VCL-Subroutinen sind vcl_recv (eingehender Request), vcl_backend_response (Antwort vom Backend), vcl_deliver (Auslieferung an den Client) und vcl_hash (Cache-Key-Berechnung). In vcl_recv wird entschieden, ob ein Request gecacht werden kann oder direkt an das Backend weitergeleitet wird.
Ein typisches Szenario ist die Cookie-Bereinigung: Viele Websites setzen Tracking-Cookies (Analytics, Advertising), die das Caching verhindern, obwohl sie für die Seitenausgabe irrelevant sind. Die VCL-Konfiguration entfernt diese Cookies aus dem Request, bevor der Cache-Key berechnet wird, und erhöht so die Hit Rate erheblich. Nur funktionale Cookies wie Session-IDs und Consent-Status werden beibehalten.
Ein weiteres häufiges Szenario ist die Grace-Mode-Konfiguration: Wenn ein Cache-Eintrag abgelaufen ist und der Backend-Server langsam antwortet oder nicht erreichbar ist, liefert Varnish im Grace Mode den abgelaufenen Eintrag aus, statt den Nutzer warten zu lassen. Die Grace-Period wird typischerweise auf mehrere Stunden bis Tage gesetzt, sodass die Website auch bei einem kompletten Backend-Ausfall aus dem Cache funktionsfähig bleibt. Für geschäftskritische Websites ist Grace Mode eine unverzichtbare Absicherung gegen Ausfälle.
Redis-Konfiguration: Memory Management und Eviction Policies
Redis speichert alle Daten im Arbeitsspeicher, was die Geschwindigkeit erklärt, aber auch die Kapazitätsplanung kritisch macht. Die maxmemory-Konfiguration begrenzt den Speicherverbrauch von Redis. Die Eviction Policy bestimmt, was passiert, wenn das Speicherlimit erreicht ist. Für Caching-Szenarien ist allkeys-lru (Least Recently Used) die empfohlene Policy: Redis entfernt die am längsten nicht abgerufenen Einträge, um Platz für neue zu schaffen.
Die Speicherdimensionierung hängt vom Anwendungsfall ab. Für einen Session-Cache mit durchschnittlich 1 KB pro Session und 10.000 gleichzeitigen Sessions sind 16 MB ausreichend. Für einen Object-Cache einer mittelgroßen Website mit 5.000 gecachten Abfragen bei durchschnittlich 5 KB pro Eintrag werden 32 bis 64 MB benötigt. Für einen Fragment-Cache bei E-Commerce-Shops mit Tausenden von Produkt-Fragmenten empfehlen wir 128 bis 512 MB. Die tatsächlich benötigte Menge lässt sich mit redis-cli info memory überwachen.
Für Produktionsumgebungen empfehlen wir eine Redis-Instanz pro Anwendungsfall: eine Instanz für Sessions (mit Persistenz via RDB-Snapshots), eine Instanz für den Object-Cache (ohne Persistenz, da die Daten bei Bedarf aus der Datenbank rekonstruiert werden) und optional eine Instanz für Message Queues. Diese Trennung verhindert, dass ein Speicherengpass im Object-Cache die Session-Daten verdrängt und umgekehrt.
Monitoring und Performance-Messung der Caching-Schichten
Die Wirksamkeit einer Caching-Architektur muss kontinuierlich gemessen werden. Die wichtigste Metrik für Varnish ist die Cache Hit Rate – der Anteil der Requests, die aus dem Cache beantwortet werden. Eine Hit Rate unter 80 Prozent deutet auf Konfigurationsprobleme hin, etwa fehlerhaftes Cookie-Handling oder zu restriktive VCL-Regeln. varnishstat und varnishtop liefern Echtzeit-Statistiken über Hit/Miss-Verhältnis, Backend-Requests und Cache-Evictions.
Für Redis sind die Memory Usage (tatsächlicher vs. konfigurierter Speicher), die Hit Rate (keyspace_hits / (keyspace_hits + keyspace_misses)), die Eviction Rate (Anzahl verdrangter Einträge) und die Latenz die zentralen Metriken. redis-cli info stats und redis-cli --latency-history liefern diese Daten. Ein plötzlicher Anstieg der Eviction Rate signalisiert, dass der konfigurierte Speicher nicht mehr ausreicht.
Die TTFB-Messung auf Seiten des Nutzers zeigt die Gesamtwirkung aller Caching-Schichten. Die Felddaten des Chrome User Experience Report (CrUX) liefern die TTFB-Verteilung für verschiedene Gerätetypen und Verbindungsgeschwindigkeiten. Ein kontinuierliches Performance-Monitoring kombiniert diese Server-seitigen und Client-seitigen Metriken und alarmiert bei Regressionen automatisch.
Caching für E-Commerce: Personalisierung und Performance vereinen
E-Commerce-Websites stellen besondere Anforderungen an die Caching-Architektur, da viele Seiten personalisierte Elemente enthalten: Warenkorb-Icon mit Artikelanzahl, kundenspezifische Preise, personalisierte Empfehlungen und Verfügbarkeitsanzeigen. Diese Personalisierung verhindert naives Full-Page-Caching, da dieselbe URL für verschiedene Nutzer unterschiedliche Inhalte enthält.
Die Lösung sind Edge Side Includes (ESI). ESI teilt die Seite in cachbare und dynamische Fragmente auf. Der Seitenrahmen – Navigation, Footer, Produktbeschreibung, statische Inhalte – wird in Varnish gecacht. Dynamische Elemente wie der Mini-Cart, der Preis für eingeloggte Kunden und die Lagerverfügbarkeit werden als ESI-Tags markiert und bei jedem Request individuell eingefügt. Varnish unterstützt ESI nativ und verarbeitet die Fragment-Zusammenführung mit minimaler Latenz.
Eine alternative Strategie ist das AJAX-basierte Nachladen: Die Basisseite wird vollständig gecacht und personalisierte Elemente werden per JavaScript-Request nachgeladen, nachdem die Seite im Browser gerendert ist. Dieser Ansatz ist einfacher zu implementieren als ESI, erzeugt aber zusätzliche HTTP-Requests und kann zu einem kurzen Flackern der personalisierten Inhalte führen. Für Shopware-basierte Shops empfehlen wir eine Kombination: ESI für kritische personalisierte Elemente (Preise) und AJAX für nicht-kritische (zuletzt angesehen, Empfehlungen).
Caching als Fundament nachhaltiger Web-Performance
Eine durchdachte Caching-Architektur ist das Fundament jeder performanten Website und ein wesentlicher Faktor für gute Core Web Vitals. Varnish als HTTP-Accelerator liefert gecachte Seiten in Millisekunden aus, Redis beschleunigt die Applikationsschicht durch In-Memory-Caching und der Browser-Cache eliminiert unnötige Netzwerk-Requests vollständig. In Kombination mit einem CDN für globale Auslieferung und einer optimierten Frontend-Auslieferung entsteht eine mehrstufige Architektur, die Antwortzeiten unter 100 Millisekunden ermöglicht und auch bei Lastspitzen stabil bleibt.
Der Schlüssel zum Erfolg liegt in der Abstimmung der Schichten aufeinander: Konsistente Cache-Header, die von Browser, CDN und Varnish gleichermaßen respektiert werden. Eine durchdachte Invalidierungsstrategie, die Änderungen schnell propagiert, ohne die Hit Rate unnötig zu senken. Und ein kontinuierliches Monitoring, das Regressionen erkennt, bevor sie die Nutzererfahrung beeinträchtigen. Mit der richtigen Server-Optimierung und Caching-Strategie wird jede Website messbar schneller – und bleibt es auch langfristig.