Varnish Cache-Warming: den Kaltstart nicht dem Kunden überlassen

Stand: Juli 2026

Ein HTTP-Cache wie Varnish macht Shops schnell — aber nur für Seiten, die schon im Cache liegen. Nach jedem Deployment, jeder Theme-Änderung, jedem größeren Purge ist der Cache kalt: Die erste Anfrage auf jede Seite muss durchs volle Backend (PHP, Datenbank) und dauert ein Vielfaches. Ohne Gegenmaßnahme zahlt diese Rechnung ausgerechnet ein echter Besucher — und die Ladezeit-Spitze landet als Ausreißer in den Core Web Vitals.

Cache-Warming dreht das um: Ein Skript ruft nach dem Purge alle wichtigen Seiten einmal selbst auf, bevor es die Kundschaft tut. Der Cache ist warm, bevor der erste Mensch klickt. Kein Pflichtprogramm — der Cache füllt sich auch organisch —, aber einer der billigsten Ladezeit-Hebel, die es gibt: ein Shell-Skript und ein Cronjob.

Die Strategie, die sich bewährt hat

  • Die Sitemap ist die URL-Quelle. Sie existiert schon, ist vollständig und aktuell — niemand pflegt URL-Listen von Hand.
  • Kategorien zuerst, dann Produkte. Kategorieseiten sind die Einstiege mit dem meisten Traffic; sie zuerst zu wärmen bringt den größten Effekt pro Minute.
  • Parallel, aber mit Augenmaß. Ein Dutzend paralleler Anfragen wärmt einen mittleren Shop in Minuten. Mehr Parallelität hilft nur, solange das Backend nicht selbst zum Engpass wird — der Warmer soll den Shop füllen, nicht fluten.
  • Die richtige Encoding-Variante wärmen. Wer Varnish Kompressions-Varianten cachen lässt (warum und wie: Brotli mit Varnish), muss beim Wärmen dieselbe Accept-Encoding-Normalisierung treffen — sonst wärmt man eine Variante, die kaum ein Browser abruft. Praxis: die Mehrheits-Variante (heute: br) gezielt wärmen, die Minderheit füllt sich organisch.
  • Consent-Zustand mitdenken. Wenn Seiten je nach Cookie-Einwilligung variieren, wärmt man den Zustand, den echte Besucher nach dem Banner haben — sonst liegt die falsche Variante im Cache.
  • Sich zu erkennen geben. Eigener User-Agent und ein internes Kennzeichen (Header), damit der Warmer in Logs und Statistiken nicht als Traffic-Anomalie auftaucht und serverseitig bevorzugt oder gedrosselt werden kann.
  • Königsklasse: Auffrischen statt nur Füllen. Wer das interne Kennzeichen in der VCL auswertet und für Warmer-Anfragen einen Miss erzwingt, macht aus dem Warmer ein Refresh-Werkzeug: Er erneuert auch warme Einträge — der Cache bleibt nicht nur gefüllt, sondern aktuell, ohne je einen Besucher auf den kalten Pfad zu schicken.

Das Gerüst

#!/bin/bash
# Varnish-Warmer: Sitemap → Kategorien zuerst → parallel wärmen
DOMAIN="www.example-shop.de"
PARALLEL=${1:-12}

URLS=$(zcat sitemap*.xml.gz | grep -oP '<loc>\K[^<]+' | sort -u)
CATS=$(echo "$URLS" | grep '/$')        # Kategorien enden auf /
PRODUCTS=$(echo "$URLS" | grep -v '/$')

warm_url() {
    curl -sL -o /dev/null \
        -w "%{http_code} %{time_total}s %{url_effective}\n" \
        -H "Accept-Encoding: br" \
        -H "Cookie: cookie-preference=1" \
        -A "CacheWarmer/1.0" \
        "$1"
}
export -f warm_url

echo "$CATS"     | xargs -P "$PARALLEL" -I{} bash -c 'warm_url "$@"' _ {}
echo "$PRODUCTS" | xargs -P "$PARALLEL" -I{} bash -c 'warm_url "$@"' _ {}

Die -w-Ausgabe liefert nebenbei ein Protokoll: Statuscode und Antwortzeit pro URL — langsame Seiten und Fehler fallen beim Wärmen auf, nicht erst beim Kunden.

Feinheiten für den Dauerbetrieb

Wann laufen lassen? Direkt nach Deployments und gezielten Purges — und optional nachts als Sicherheitsnetz für Einträge, deren TTL abgelaufen ist. Wer mit Tag-basiertem Invalidieren arbeitet (xkey/Ban), kann nach einem gezielten Purge auch gezielt nachwärmen, statt alles anzufassen.

Erfolg messen: varnishstat zeigt die Trefferrate (cache_hit vs. cache_miss); nach einem Warm-Lauf sollte die Miss-Rate für Sitemap-URLs gegen null gehen. Die Antwortzeiten aus dem Warm-Protokoll sind zugleich eine ehrliche Backend-Benchmark — gecachte Antworten liegen im einstelligen Millisekundenbereich, alles andere ist Backend-Arbeit.

Was man nicht wärmt: Warenkorb, Checkout, Konto — alles mit Session-Bezug gehört nicht in einen shared Cache und damit auch nicht in den Warmer.


Zum selben Themenkreis: Brotli-Kompression mit Varnish — inklusive der Varianten-Falle, die auch beim Wärmen zuschlägt.