Wenn eine Website sich „zäh“ anfühlt, liegt das nicht immer an schlechtem Code oder einem langsamen Server. Häufig werden Dateien bei jedem Seitenaufruf neu geladen, obwohl sie sich kaum ändern: Bilder, CSS, JavaScript oder sogar API-Antworten. Genau hier hilft HTTP Caching: Der Browser (und oft auch ein CDN) darf Antworten zwischenspeichern und später wiederverwenden. Das spart Zeit, Bandbreite und reduziert Serverlast.
Damit Caching zuverlässig funktioniert, braucht es klare Regeln. Diese Regeln werden über HTTP-Header gesteuert. Der wichtigste ist Cache-Control. Für fortgeschrittene Fälle kommen Validatoren wie ETag ins Spiel. In diesem Artikel wird Schritt für Schritt erklärt, wie das Zusammenspiel funktioniert – ohne Mythen, aber mit Praxisbezug.
Wie Browser entscheiden, ob sie etwas erneut laden
Beim Caching gibt es im Kern zwei Strategien:
- Freshness (Frische): Die Antwort gilt für eine bestimmte Zeit als „frisch“. Solange diese Zeit nicht abgelaufen ist, wird sie direkt aus dem Cache genutzt – ganz ohne Anfrage an den Server.
- Validation (Validierung): Ist die Antwort „abgelaufen“, kann der Browser den Server fragen, ob sich die Ressource geändert hat. Wenn nicht, kommt eine kurze Antwort (ohne kompletten Inhalt) und der Browser nutzt seinen Cache weiter.
Wichtig: Caching ist nicht „ein Schalter“, sondern eine Vereinbarung zwischen Client (Browser), möglichen Zwischenstationen (CDN/Proxy) und Server. Ohne klare Header trifft der Browser eigene, oft konservative Entscheidungen – oder cached gar nicht.
Was wird typischerweise gecacht (und was nicht)?
Sehr gut geeignet sind sogenannte „statische Assets“: CSS, JavaScript-Bundles, Bilder, Fonts. Auch API-Responses können sinnvoll gecacht werden, wenn sie nicht pro Nutzer variieren oder wenn eine kurze Cache-Dauer akzeptabel ist.
Vorsichtig sollte man bei personalisierten Inhalten sein (z. B. „Hallo, Name“), bei alles was von Cookies/Authorization abhängt und bei Antworten, die sicherheitsrelevant sind. Hier ist korrektes Setzen von Cache-Regeln entscheidend.
Cache-Control richtig einsetzen: die wichtigsten Direktiven
Cache-Control ist der zentrale Hebel. Er kann sowohl in Responses vom Server als auch in Requests vom Browser vorkommen. Für den Alltag reicht meist der Response-Header.
max-age: Wie lange darf der Browser die Antwort nutzen?
Mit max-age (in Sekunden) sagst du: „Diese Antwort ist ab jetzt für X Sekunden frisch.“ Solange diese Zeit läuft, wird die Ressource aus dem Cache geladen.
Typische Anwendung: versionierte Dateien, die sich nur ändern, wenn sich ihr Dateiname ändert (z. B. app.3f2a1c.js). Dann kann die Cache-Zeit lang sein, weil neue Versionen ohnehin unter neuer URL erscheinen.
public vs. private: Wer darf cachen?
- public: Darf von Browsern und Shared Caches (z. B. CDN) gespeichert werden.
- private: Darf nur im Browser-Cache liegen, nicht in gemeinsamen Caches.
Für öffentliche Assets ist public passend. Für personalisierte Seiten ist private oft die sichere Wahl, wenn überhaupt gecacht wird.
no-store und no-cache: ähnlich klingend, anders gemeint
Hier entstehen viele Missverständnisse:
- no-store: Nichts davon darf gespeichert werden. Auch nicht kurzzeitig. Das ist die strengste Option, z. B. für sensible Inhalte.
- no-cache: Darf gespeichert werden, aber muss vor Nutzung beim Server validiert werden. Praktisch bedeutet das: ohne erneute Prüfung nicht verwenden.
Wer „gar kein Caching“ will, meint meist no-store. Wer „bitte immer prüfen, ob es neu ist“ will, meint oft no-cache.
must-revalidate: abgelaufen heißt wirklich abgelaufen
Mit must-revalidate erzwingst du: Wenn die Antwort nicht mehr frisch ist, darf sie nicht „auf gut Glück“ genutzt werden. Das ist für Inhalte relevant, bei denen alte Daten problematisch wären.
Validierung mit ETag und Last-Modified: weniger Daten, gleiche Sicherheit
Wenn eine Ressource abgelaufen ist, muss nicht automatisch der komplette Inhalt erneut geladen werden. Stattdessen kann der Browser eine Validierungsanfrage stellen.
ETag: Fingerabdruck einer Ressource
Der Server kann einen ETag mitsenden. Das ist ein Identifier, der sich ändert, wenn sich die Ressource ändert. Beim nächsten Mal sendet der Browser diesen Wert in einer Bedingung mit (If-None-Match). Wenn der Inhalt gleich ist, antwortet der Server mit „nicht geändert“ und ohne Body. Der Browser nutzt dann seinen Cache weiter.
Das ist besonders nützlich, wenn du keine langen Cache-Zeiten setzen kannst oder willst, aber trotzdem unnötige Datenübertragung vermeiden möchtest.
Last-Modified: Datum statt Fingerabdruck
Alternativ kann der Server Last-Modified senden. Der Browser fragt später per If-Modified-Since nach. Das ist einfacher, aber weniger präzise als ETag (z. B. wenn mehrere Änderungen innerhalb kurzer Zeit passieren). In der Praxis werden beide Mechanismen oft kombiniert oder je nach Setup genutzt.
Statische Assets: langfristig cachen ohne Update-Probleme
Ein häufiger Fehler: CSS/JS werden lange gecacht, aber der Dateiname bleibt gleich. Dann sehen Nutzer nach einem Deploy noch das alte Layout oder bekommen JavaScript-Fehler, weil HTML und JS nicht zusammenpassen.
Die robuste Lösung: versionierte Dateinamen
Wenn Build-Tools (z. B. in Frontend-Setups) Hashes in Dateinamen schreiben, kann Caching aggressiv sein, ohne dass Updates hängen bleiben. Das Prinzip ist simpel:
- Neue Version → neuer Dateiname → neue URL → Browser muss neu laden.
- Alter Dateiname bleibt gültig → darf lange im Cache liegen.
Was ist mit HTML?
HTML selbst ändert sich häufiger und sollte meist kürzer gecacht werden, damit neue Asset-Links schnell ankommen. Häufig ist es sinnvoll, HTML eher kurz frisch zu halten und Assets langfristig zu cachen.
API-Antworten cachen: hilfreich, aber nur mit klaren Regeln
Auch JSON-Antworten aus APIs können gecacht werden, etwa bei öffentlichen Katalogdaten oder „Top-Artikel“-Listen. Entscheidend ist: Variiert die Antwort pro Nutzer? Dann darf sie nicht in einem Shared Cache landen – oder muss über passende Header korrekt getrennt werden.
Vary: wenn sich Antworten je nach Request-Header unterscheiden
Wenn eine Antwort abhängig von bestimmten Request-Headern ist (zum Beispiel Sprache), braucht es Vary. Damit wird dem Cache gesagt, nach welchen Headern unterschiedliche Varianten gespeichert werden müssen.
Beispielgedanke: Eine Ressource liefert Deutsch oder Englisch abhängig vom Header. Ohne Vary könnte ein Cache die „deutsche“ Antwort an englische Nutzer ausliefern.
Typische Stolperfallen bei APIs
- Authorization/Cookies werden genutzt, aber Antworten sind nicht als private gekennzeichnet.
- Fehlende oder falsche Vary-Header bei Sprach- oder Formatvarianten.
- Unklare Cache-Zeiten: zu lang (Daten veralten) oder zu kurz (kein Effekt).
Praktische Schritte: Caching einführen und sicher prüfen
Damit Caching im Alltag nicht zur „Blackbox“ wird, helfen ein paar feste Schritte. Die Idee: erst planen, dann kontrolliert ausrollen, dann messen.
Kurze Schrittfolge für ein sauberes Setup
- Assets identifizieren: Was ist wirklich statisch (CSS/JS/Bilder/Fonts)?
- Build/Deploy prüfen: Werden versionierte Dateinamen genutzt (Hash/Fingerprint)?
- Für Assets passende Cache-Control setzen (lange Frische bei versionierten Dateien).
- HTML bewusst kürzer cachen oder validieren lassen.
- Für APIs entscheiden: Welche Endpunkte sind cachebar, welche sind personalisiert?
- Mit DevTools prüfen: Werden Responses aus dem Cache geladen, und welche Header sind gesetzt?
- Änderungsfall testen: Nach einem Deploy im privaten Browserfenster prüfen, ob neue Dateien sicher geladen werden.
Kurzer Vergleich: lange Cache-Zeiten vs. häufige Validierung
| Ansatz | Vorteil | Risiko |
|---|---|---|
| Lange Frische (max-age hoch) bei versionierten Assets | Sehr schnell, kaum Serveranfragen | Ohne Versionierung bleiben Nutzer ggf. auf alten Dateien hängen |
| Kurze Frische + Validierung (ETag/Last-Modified) | Weniger Datenübertragung, Updates kommen zuverlässig | Mehr Requests, besonders bei vielen Ressourcen |
| no-store für sensible Inhalte | Maximale Sicherheit gegen Cache-Leaks | Performance-Vorteile gehen verloren |
Fehlerbilder aus der Praxis und wie sie sich vermeiden lassen
„Nach dem Release ist das Layout kaputt“
Oft zeigt das HTML schon auf neue Klassen/Dateien, aber der Browser nutzt noch altes CSS oder altes JS aus dem Cache. Abhilfe: versionierte Dateinamen für Assets und sinnvolle Cache-Regeln, damit alte Dateien ruhig lange bleiben dürfen – aber neue URLs neue Inhalte erzwingen.
„Im CDN sehen manche Nutzer falsche Inhalte“
Das passiert, wenn personalisierte Antworten als public gecacht werden oder wenn Vary fehlt. Für Nutzer-spezifische Antworten gilt: lieber private oder gar nicht cachebar machen, und bei Varianten immer klar sagen, wonach getrennt werden muss.
„Caching bringt nichts, alles lädt trotzdem ständig neu“
Dann fehlen oft Cache-Control-Header, oder max-age ist sehr kurz, oder es wird ungewollt no-store gesetzt. Auch Redirect-Ketten oder unterschiedliche URLs (z. B. mit unnötigen Query-Parametern) können Caches aushebeln.
Wer tiefer in HTTP-Grundlagen einsteigen möchte, findet hilfreiche Ergänzungen bei HTTP-Request-Header verstehen und bei HTTP-Statuscodes verstehen. Für API-Design-Entscheidungen passt außerdem REST-APIs im Web verstehen.

