Websites wirken sofort schneller, wenn der Browser weniger laden muss. Hier hilft HTTP Caching: Richtig eingestellt reduziert es Netzwerklast, TTFB (Zeit bis zur ersten Antwort) und Serverkosten. Dieser Leitfaden erklärt die wichtigsten Header, sinnvolle Standards und zeigt, wie sich Assets, HTML und APIs sauber cachen lassen – ohne Nutzer oder Redaktion auszubremsen.
HTTP Caching verstehen: Freshness und Validation
Browser-Cache, Proxy-Cache, CDN – wer speichert was?
Zwischen Server und Nutzer liegen oft mehrere Caches: der Browser-Cache, ein Proxy im Unternehmensnetz, und ein Content Delivery Network (CDN). Der Browser speichert Ressourcen direkt beim Nutzer. Proxies betreffen ganze Netzwerke. Ein CDN verteilt Kopien von Inhalten weltweit an Edge-Standorte. Ziel: Weniger Anfragen zum Ursprungsserver, kürzere Wege, schnellere Auslieferung.
Freshness vs. Validation: zwei Wege zum schnellen Treffer
Freshness bedeutet: Eine Ressource gilt als frisch und kann sofort aus dem Cache kommen (z. B. „max-age=3600“). Validation bedeutet: Der Cache fragt kurz beim Server nach, ob sich die Ressource geändert hat – ideal mit ETag oder Last-Modified. Bei Erfolg liefert der Server „304 Not Modified“ zurück, und nur wenige Header gehen über die Leitung.
Cache-Control im Detail: wichtige Direktiven
public, private, max-age, no-store – Basiseinstellungen
Der Header „Cache-Control“ steuert, wie Caches arbeiten. Basale Direktiven:
- public: Antwort ist für jeden Cache geeignet (Browser, Proxies, CDNs).
- private: Nur im Browser-Cache speichern (nützlich für personalisierte Seiten).
- max-age=Sekunden: Wie lange die Ressource frisch ist (z. B. max-age=31536000 für Versionierte Assets).
- no-store: Nichts speichern, weder im Browser noch in Zwischen-Caches. Für sensible Daten und Login-Seiten geeignet.
s-maxage, stale-while-revalidate, stale-if-error – Profi-Werkzeuge
Weitere Direktiven für mehr Kontrolle:
- s-maxage=Sekunden: Überschreibt max-age für Shared Caches (z. B. CDNs).
- stale-while-revalidate=Sekunden: Liefert eine leicht veraltete Kopie, während im Hintergrund aktualisiert wird.
- stale-if-error=Sekunden: Wenn der Origin-Server Fehler liefert, kommt eine ältere Kopie, statt einer Fehlermeldung.
Für statische Assets lohnt „immutable“: Der Browser weiß, dass sich die Datei unter derselben URL nicht ändert (nur mit Versionshashs verwenden).
Kleine Tabelle: Cache-Control Direktiven und Wirkung
| Direktive | Beispiel | Wirkung |
|---|---|---|
| max-age | max-age=86400 | 24 Stunden frisch, ohne Serverkontakt. |
| s-maxage | s-maxage=600 | CDNs/Proxies cachen 10 Minuten, Browser nach max-age. |
| public/private | public | Erlaubt/verbietet Shared Caches wie CDN/Proxy. |
| no-store | no-store | Keine Speicherung; für sensitive Inhalte. |
| stale-while-revalidate | stale-while-revalidate=30 | 30 s alte Kopie zulassen, während im Hintergrund aktualisiert wird. |
| immutable | immutable | Datei ändert sich unter der URL nicht (nur mit Hash nutzen). |
ETag und Last-Modified sinnvoll einsetzen
Starke vs. schwache ETags
ETags sind Prüfsummen für Inhalte. Starke ETags ändern sich bei jedem Byte-Unterschied; schwache ETags (präfix „W/“) signalisieren „nahezu gleich“. Für Dateien mit Versionshashs (z. B. app.3f4a7.css) sind starke ETags ideal. Für HTML, das sich leicht ändert (z. B. kleine Timestamps), können schwache ETags ausreichend sein.
Conditional Requests mit If-None-Match/If-Modified-Since
Der Browser sendet „If-None-Match“ (für ETag) oder „If-Modified-Since“ (für Last-Modified), um eine Validierung auszulösen. Hat sich die Ressource nicht geändert, antwortet der Server mit „304 Not Modified“. Vorteil: Minimale Datenübertragung, schnelle Antwort.
Praxis-Strategien: Assets, HTML, APIs
Statische Assets (CSS/JS/Bilder) mit Versionierung
Best Practice: Cache-Busting per Dateinamen. Beispiel: app.3f4a7.js. Dazu: Cache-Control: public, max-age=31536000, immutable. Ergebnis: Der Browser lädt diese Datei lange nicht neu. Neue Deployments erzeugen neue Dateinamen – Caches erkennen die Änderung sofort.
HTML-Seiten und SSR: kurz cachen, schnell revalidieren
HTML ist oft dynamisch (Anmeldung, Warenkorb, Personalisierung). Eine gängige Einstellung: Cache-Control: public, s-maxage=60, stale-while-revalidate=30 bei Auslieferung über ein Edge-Netzwerk. So bleiben Seiten gefühlt frisch, ohne bei jedem Aufruf den Origin-Server zu belasten. Personalisierte Bereiche sollten private oder no-store nutzen.
APIs: GET cachen, POST nicht
Idempotente GET-Endpoints lassen sich cachen. Arbeite mit ETag/Last-Modified, kurzen max-age-Werten und Conditional Requests. Mutable Endpoints (POST, PUT, PATCH, DELETE) sollten nicht gecacht werden. Antworten mit Nutzerdaten eher „private“ oder „no-store“ kennzeichnen.
Rollout und Tests: sicher in die Produktion
Header prüfen in DevTools und mit curl
Im Browser: Netzwerk-Panel öffnen, Ressource anklicken, Antwort-Header kontrollieren. Interessant sind Cache-Control, ETag/Last-Modified, Age (zeigt Cache-Hits an) und Status 304 bei Validierung. Per CLI: curl -I https://domain.tld/asset.css zeigt nur die Header. Wiederhole Anfragen, um Cache-Verhalten zu beobachten.
Edge Cases: Logins, Cookies, Personalisierung
Login-Seiten und Kontobereiche sollten no-store nutzen. Achte auf Cookies: Wenn Seiten anhand von Cookies variieren, muss der Cache das berücksichtigen (z. B. „Vary: Cookie“ – in CDNs mit Vorsicht, da explodierende Variantenzahl). Für Feature-Flags und AB-Tests ist Edge-Side-Rendering oder ein kurzer s-maxage plus schnelle Revalidierung sinnvoll.
Monitoring und Optimierung
Cache-Hit-Rate messen
Die Cache-Hit-Rate (Anteil der Antworten aus Caches) zeigt, wie gut die Strategie wirkt. Metriken aus CDN, Reverse Proxy und Application Logs zusammenführen. Bei niedrigen Raten: Prüfe, ob URLs stabil versioniert sind, ob Query-Parameter differenzieren, und ob unnötige „no-store“-Antworten die Caches blockieren.
Einfluss auf Nutzererlebnis und Core Web Vitals
Gutes Caching senkt LCP (Largest Contentful Paint), da große Assets (Hero-Bilder, Fonts, CSS) oft schon im Browser liegen. FID/INP profitieren indirekt durch weniger Hauptthread-Blockaden beim Laden. Vorsicht bei zu langem Caching von HTML: Veraltete Inhalte können UX schmälern. Deshalb kurze Freshness plus schnelle Revalidierung.
Häufige Fehler – und bessere Alternativen
no-cache vs. no-store korrekt unterscheiden
„no-cache“ heißt nicht „nichts cachen“, sondern „vor Nutzung neu validieren“. „no-store“ verbietet jede Speicherung. Für sensible Inhalte (z. B. Kontoauszüge) ist no-store die richtige Wahl. Für häufig wechselnde, aber unkritische Inhalte ist „no-cache“ mit ETag oft besser.
ETag pro Deployment aktualisieren
Wenn Build-Prozesse Assets minimieren, muss das ETag mit dem Dateiinhalte-Hash übereinstimmen. Andernfalls liefert der Server 304, obwohl sich die Datei faktisch geändert hat. Für HTML empfiehlt sich ein klar definierter ETag-Generator oder Last-Modified auf Basis des fertigen Renderings.
Konkrete Defaults für den Start
Produkttaugliche Einstellungen für typische Ressourcen
Bewährte Startwerte, die in vielen Setups gut funktionieren:
- Assets (CSS/JS/Bilder mit Hash): Cache-Control: public, max-age=31536000, immutable; ETag optional.
- Schriftarten: wie Assets, ggf. zusätzlich „Cross-Origin Resource Sharing“ korrekt setzen, um Double-Downloads zu vermeiden.
- HTML (SSR/SSG mit regelmäßigen Updates): Cache-Control: public, s-maxage=60, stale-while-revalidate=30; ETag stark oder schwach.
- API-GET (nicht personalisiert): Cache-Control: public, max-age=60, stale-while-revalidate=30; ETag/Last-Modified aktiv.
- Personalisierte Seiten: Cache-Control: private, no-store; keine Speicherung in Shared Caches.
So geht’s in Kürze:
- Dateinamen mit Versionshash einführen (Build-Pipeline anpassen).
- Für Assets: lange max-age plus immutable setzen.
- Für HTML/API: kurze Freshness, Validierung mit ETag aktivieren.
- Login- und Konto-Seiten: no-store und ggf. private.
- Testen: DevTools-Header prüfen, 304-Validierung verifizieren, Hit-Rate beobachten.
FAQ: Antworten auf typische Fragen
Ist ein CDN zwingend nötig für gutes Caching?
Nein, aber ein CDN bringt Nähe zum Nutzer und entlastet den Origin-Server. Mit korrekten Headern profitieren auch Browser- und Proxy-Caches. Bei internationaler Zielgruppe ist ein CDN fast immer sinnvoll.
Was ist besser: ETag oder Last-Modified?
ETag ist genauer, weil es auf den Inhalt abzielt. Last-Modified reicht oft, wenn Änderungszeitpunkte zuverlässig sind. In der Praxis funktionieren beide gut; ETag bietet mehr Sicherheit bei kleinen Änderungen.
Wie gehe ich mit häufig aktualisierten Inhalten um?
Kurze Freshness (z. B. 30–120 s) plus Validierung, optional mit „stale-while-revalidate“, hält Seiten gefühlt aktuell und schützt den Server vor Lastspitzen.
Beispiel-Header für den Alltag
Vorlagen, die sich in vielen Projekten bewähren
Assets (versioniert): Cache-Control: public, max-age=31536000, immutable
HTML (SSR): Cache-Control: public, s-maxage=60, stale-while-revalidate=30
API-GET: Cache-Control: public, max-age=60, stale-while-revalidate=30; ETag: „…“
Sensitive Bereiche: Cache-Control: no-store
Zusammenarbeit von Cache-Control und ETag
Schnell liefern, smart prüfen
Die beste Performance entsteht, wenn Freshness und Validation kombiniert werden: Assets liefern mit langer Freshness sofort, HTML und APIs bleiben kurzfristig frisch und werden bei Bedarf mit ETag schnell validiert. So kommen Nutzer zügig an Inhalte, während Serverlast und Bandbreite sinken.

