Was beim Sprung zurück im Browser passiert
Der Back/Forward-Cache, kurz bfcache, ist kein gewöhnlicher Zwischenspeicher für Dateien. Er hält die komplette Seite samt JavaScript-Zustand im Arbeitsspeicher fest. web.dev beschreibt den Unterschied unmissverständlich: bfcache sei ein Abbild der gesamten Seite im Speicher einschließlich des JavaScript-Heaps, während der HTTP-Cache nur die Antworten zuvor gestellter Anfragen enthalte (web.dev). Beim Sprung zurück wird dieses Abbild wieder eingeblendet. Es gibt keine neue Netzwerkanfrage, keinen neuen Aufbau des Dokuments und kein neues load-Ereignis - also keinen der Auslöser, auf die ein klassisches Messskript wartet.
Die Technik ist keine Randerscheinung. Alle großen Browser bringen einen bfcache mit, Chrome seit Version 96, dazu Firefox und Safari (web.dev). Und sie greift häufiger, als die meisten Auswertungen vermuten lassen: Nach Chrome-Nutzungsdaten ist jede zehnte Navigation am Desktop und jede fünfte auf dem Handy eine Vor- oder Zurück-Navigation (web.dev). Nicht jede davon landet im Cache, dazu später mehr, aber die Größenordnung zeigt, worüber wir reden. Bei einer Website mit ausgeprägter interner Navigation entscheidet dieser Anteil darüber, ob die Auswertung die Realität abbildet oder eine gefilterte Teilmenge davon.
- Den kompletten DOM-Baum samt berechneter Stile und Scrollposition
- Den JavaScript-Heap mit allen Variablen, Objekten und laufenden Zustandsmaschinen
- Pausierte Timer und Beobachter, die beim Zurückholen dort weitermachen, wo sie eingefroren wurden
- Den Inhalt von Formularfeldern, ohne dass die Seite ihn selbst sichern muss
Der HTTP-Cache spart Netzwerkanfragen, der Seitenaufbau läuft trotzdem komplett neu ab: Auszeichnung auswerten, Stile berechnen, Skripte ausführen, Ereignisse auslösen. Der bfcache überspringt genau diesen Teil. Für die Messung ist das der entscheidende Unterschied, denn alle üblichen Aufhänger - DOMContentLoaded, load, ein frisch ausgeführtes Messskript - entstehen ausschließlich beim echten Aufbau.
Warum die Seitenaufrufe sinken, wenn die Seite schneller wird
web.dev benennt die Folge für die Messung ausdrücklich: Wer ein Analysewerkzeug einsetzt, um Besuche auf der eigenen Seite zu messen, bemerke unter Umständen einen Rückgang der insgesamt gemeldeten Seitenaufrufe, sobald Chrome den bfcache für mehr Nutzer aktiviere (web.dev). Der Satz davor ist der unangenehmere: Sehr wahrscheinlich untererfassen Sie Seitenaufrufe aus anderen Browsern mit bfcache bereits heute, weil viele verbreitete Analytics-Bibliotheken bfcache-Wiederherstellungen nicht als neue Seitenaufrufe messen (web.dev).
Das erklärt ein Muster, das in Agenturen regelmäßig zu Fehlschlüssen führt. Nach einem Performance-Projekt oder nach einem Browser-Update sinken die Seitenaufrufe, ohne dass Kampagnen, Rankings oder Serverprotokolle einen Einbruch zeigen. Die naheliegende Deutung - weniger Besucher - ist falsch. Es sind dieselben Besucher, die nur einen Teil ihrer Navigationen an der Messung vorbeischleusen. Wer den Unterschied zwischen Serverprotokoll und Messskript kennt, findet die Lücke in einer Stunde; wer beides für dasselbe hält, sucht wochenlang an der falschen Stelle.
| Navigation | Browser baut die Seite neu auf | Messskript ohne pageshow | CrUX-Felddaten |
|---|---|---|---|
| Erster Aufruf | ja | zählt | zählt |
| Neu laden | ja | zählt | zählt |
| Zurück, aus dem bfcache | nein | zählt nicht | zählt |
| Zurück, ohne bfcache | ja | zählt | zählt |
| Vorwärts, aus dem bfcache | nein | zählt nicht | zählt |
Die Tabelle zeigt auch, warum die Abweichung nicht gleichmäßig über alle Seiten verteilt ist. Eine Artikelübersicht, zu der Leser nach jedem Beitrag zurückspringen, verliert deutlich mehr als eine Landingpage, die man einmal betritt und wieder verlässt. Ausgerechnet die Seiten mit der besten internen Navigation sehen in der Auswertung am schwächsten aus. Wie sich Wege durch eine Website sauber rekonstruieren lassen, steht in unserem Beitrag zu Nutzerpfaden und Seitenübergängen.
Die Verteilung kippt nach unten, obwohl es schneller wurde
Der zweite Schaden ist leiser als die fehlenden Seitenaufrufe und trifft ausgerechnet die Kennzahlen, mit denen Agenturen ihre Arbeit belegen. Entscheidend ist, welche Seitenaufrufe wegfallen: Nach web.dev wären die Ladevorgänge, die durch bfcache-Wiederherstellungen ersetzt werden, wahrscheinlich einige der schnellsten Ladevorgänge im Datensatz gewesen (web.dev). Es verschwindet also nicht irgendein Querschnitt, sondern genau das obere Ende.
Das Ergebnis sind weniger schnelle Ladevorgänge im Datensatz, was die Verteilung wahrscheinlich langsamer erscheinen lässt - obwohl sich die vom Nutzer erlebte Leistung wahrscheinlich verbessert hat.
— web.dev, Back/forward cache
CrUX misst am 75. Perzentil, also an dem Wert, den 75 Prozent der Seitenaufrufe erreichen (web.dev). Nimmt man dem Datensatz die schnellsten Aufrufe weg, wandert dieser Schnittpunkt nach hinten. Die Seite ist für den Nutzer schneller geworden, die Zahl im Bericht schlechter. Wer daraufhin an den falschen Stellen nachbessert, verschlechtert das Ergebnis weiter - die Trennung zwischen Feld- und Labordaten steht deshalb nicht am Ende, sondern am Anfang jeder Ursachensuche (Felddaten gegen Labordaten).
Bei einer bfcache-Wiederherstellung sind LCP und FCP identisch (web.dev). Wer beide Werte unverändert weiterschreibt, mischt zwei Messgrößen, die sonst deutlich auseinanderliegen, und erzeugt eine Verteilung, die es so nie gab.
Für Cumulative Layout Shift empfiehlt web.dev, den vorhandenen Performance Observer weiter zu nutzen, den aktuellen CLS-Wert aber auf 0 zurückzusetzen (web.dev). Sonst zählt die wiederhergestellte Ansicht Verschiebungen mit, die längst berichtet wurden.
Für Interaction to Next Paint gilt dasselbe: Observer behalten, den aktuellen INP-Wert auf 0 zurücksetzen (web.dev). Andernfalls schleppt die Seite die längste Interaktion der vorigen Ansicht in den neuen Messabschnitt.
web.dev rät, alle Ladekennzahlen mit ihrem jeweiligen Navigationstyp zu versehen: navigate, reload, back_forward oder prerender (web.dev). Ohne diese Kennzeichnung lässt sich später nicht mehr trennen, welcher Wert aus welcher Art von Navigation stammt.
pageshow und persisted: der Zweizeiler, der die Lücke schließt
Die Abhilfe ist klein und steht in derselben Quelle. Um bfcache-Wiederherstellungen in die Zählung der Seitenaufrufe aufzunehmen, setzen Sie Listener für das pageshow-Ereignis und prüfen die Eigenschaft persisted (web.dev). Diese Eigenschaft ist true, wenn die Seite aus dem bfcache wiederhergestellt wurde, und andernfalls false (web.dev). Mehr braucht es für den ersten Schritt nicht - die Sorgfalt steckt in den beiden Fallen, die gleich danach kommen.
// Ersten Aufbau und bfcache-Wiederherstellung getrennt behandeln
window.addEventListener('pageshow', (ereignis) => {
const eintrag = performance.getEntriesByType('navigation')[0];
const typ = ereignis.persisted
? 'back_forward'
: (eintrag ? eintrag.type : 'navigate');
if (ereignis.persisted) {
// Kein neuer Seitenaufbau: Zählerstände der vorigen Ansicht verwerfen
setzeWebVitalsZurueck();
}
sendeSeitenaufruf({
pfad: location.pathname,
navigationstyp: typ,
ausBfcache: ereignis.persisted === true
});
});
window.addEventListener('pagehide', (ereignis) => {
// persisted === true bedeutet: die Seite wandert in den bfcache
leereWarteschlange({ sitzungsende: ereignis.persisted !== true });
});Zwei Fallen stecken darin. Erstens feuert pageshow auch beim ersten Aufbau, und zwar laut MDN nach dem load-Ereignis (MDN). Wer den Listener ohne Fallunterscheidung anhängt, zählt den ersten Aufruf doppelt und macht aus einer Untererfassung eine Übererfassung. Zweitens verspricht der Name mehr, als das Ereignis hält: Trotz seines Namens feuert pageshow nicht in dem Moment, in dem die Seite dem Nutzer tatsächlich angezeigt wird (MDN). Für die tatsächliche Sichtbarkeit bleibt visibilitychange zuständig.
Ein zusätzlicher Seitenaufruf allein reicht nicht. Der wiederhergestellte Zustand bringt die Messwerte der vorigen Ansicht mit: gesammelte Layoutverschiebungen, die längste Interaktion, angefangene Zeitmessungen. Ohne Rücksetzen wandern diese Werte ein zweites Mal in den Bericht und verzerren ihn in die andere Richtung. Welche Ereignisse unser JavaScript-Tracker dafür auswertet, steht in der Dokumentation.
Navigationstyp mitschreiben statt Durchschnitte verrühren
Ein reiner Zähler beantwortet die nächste Frage nicht: Wie viele Ihrer Navigationen kommen überhaupt aus dem Cache? Dafür trägt jede Navigation ihren Typ mit sich. PerformanceNavigationTiming kennt die Werte navigate, reload, back_forward und prerender (web.dev); back_forward bedeutet laut MDN, dass die Navigation über die Verlaufsnavigation des Browsers erfolgt ist (MDN). Wer diesen Typ an jede Kennzahl hängt, kann die Verteilungen getrennt auswerten, statt sie zu einem Durchschnitt zu verrühren, in dem sich die beiden Effekte gegenseitig verdecken.
function navigationstyp() {
const eintrag = performance.getEntriesByType('navigation')[0];
return eintrag ? eintrag.type : 'navigate';
}
// Gründe sammeln, warum eine Seite NICHT aus dem bfcache kam
function bfcacheHindernisse() {
const eintrag = performance.getEntriesByType('navigation')[0];
if (!eintrag || !('notRestoredReasons' in eintrag)) {
return null;
}
return eintrag.notRestoredReasons;
}- Seitenaufrufe je Navigationstyp getrennt ausweisen, nicht nur als Summe
- LCP, INP und CLS je Navigationstyp gruppieren - back_forward liegt systematisch besser
- Den Anteil der back_forward-Navigationen als eigene Kennzahl führen und über die Zeit beobachten
- Den Anteil der Wiederherstellungen an allen back_forward-Navigationen messen: das ist Ihre Trefferquote
- Vergleiche zwischen Zeiträumen nur innerhalb desselben Navigationstyps ziehen
Warum Ihre Seite gar nicht erst in den Cache kommt
Eine hohe Trefferquote ist kein Selbstläufer. web.dev stellt klar, dass Betreiber keine bfcache-Trefferquote von 100 Prozent für alle back_forward-Navigationen erwarten sollten (web.dev). Der häufigste selbstverschuldete Ausschlussgrund ist ein alter Bekannter: Auf Desktop-Chrome und -Firefox wurde entschieden, Seiten für den bfcache ungeeignet zu machen, sobald sie einen unload-Listener setzen - weniger riskant, aber es disqualifiziert viele Seiten (web.dev).
Genau dieser Listener verschwindet gerade. Chrome beschreibt die schrittweise Abschaffung so, dass die Voreinstellung nach und nach geändert wird und unload-Handler auf Seiten nicht mehr feuern, sofern eine Seite sie nicht ausdrücklich wieder aktiviert (Chrome for Developers). Der Rollout auf alle Ursprünge begann 2026 und läuft über acht Meilensteine, also etwa 32 Wochen (Chrome for Developers). Die Begründung nennt dieselbe Quelle: Auf Desktop-Chrome und -Firefox ist unload zwar einigermaßen verlässlich, wirkt sich aber negativ auf die Leistung einer Seite aus, weil es die Nutzung des bfcache verhindert (Chrome for Developers). Was das für die Datenerfassung beim Verlassen bedeutet, steht im Beitrag zum Ende von unload in Chrome.
- unload-Listener: auf dem Desktop ein harter Ausschluss (web.dev). Ersatz ist pagehide, das in allen Fällen feuert, in denen unload feuert, und zusätzlich dann, wenn eine Seite in den bfcache gelegt wird (web.dev).
- Cache-Control: no-store schränkt die Eignung einer Seite für den bfcache ein und sollte nur auf Seiten mit sensiblen Inhalten stehen, bei denen Zwischenspeicherung jeder Art nie angebracht ist (web.dev).
- Offene Verbindungen und laufende Beobachter: web.dev empfiehlt nachdrücklich, Verbindungen zu schließen und Beobachter beim pagehide- oder freeze-Ereignis zu entfernen oder zu trennen (web.dev).
- Verweise über window.opener: es sei am besten, das Anlegen von window.opener-Verweisen zu vermeiden (web.dev).
Warum eine bestimmte Seite draußen blieb, muss man nicht raten. Chrome hat die NotRestoredReasons-API ergänzt, um offenzulegen, weshalb Seiten den bfcache nicht nutzen, damit Entwickler ihre Trefferquoten verbessern können (web.dev). MDN beschreibt die Eigenschaft notRestoredReasons von PerformanceNavigationTiming als Rückgabe eines Objekts mit Berichtsdaten zu den Gründen, aus denen das aktuelle Dokument bei der Navigation von der Nutzung des Back/Forward-Cache ausgeschlossen war (MDN). Eine Einschränkung nennt dieselbe Seite: Die Eigenschaft kann auch dann null zurückgeben, wenn der Navigationstyp als back/forward gemeldet wird (MDN). Ergänzend prüft Lighthouse seit Version 10.0 den bfcache in einem eigenen Audit (web.dev).
CrUX und die eigene Messung auseinanderhalten
Wer die eigenen Zahlen mit dem Chrome User Experience Report vergleicht, kurz CrUX, stößt auf dieselbe Ursache aus der anderen Richtung. CrUX wertet bfcache-Wiederherstellungen als Seitennavigationen, obwohl sie zu keinem herkömmlichen Seitenaufbau führen (web.dev). Weil die Web-APIs sie nicht als Seitenaufbau behandeln, müssen RUM-Lösungen zusätzliche Schritte gehen, damit diese Seiten mitgezählt werden, wenn sie zu CrUX passen sollen (web.dev). Und weil es sich um erheblich schnellere Ladevorgänge handelt, die insgesamt zu besseren gemeldeten Werten führen können, ergibt ihr Fehlen schlechtere Gesamtwerte (web.dev).
Solange die eigene Messung bfcache-Wiederherstellungen auslässt und CrUX sie zählt, vergleichen Sie zwei verschiedene Grundgesamtheiten. Die Differenz verschwindet nicht durch häufigeres Messen, sondern erst, wenn beide Seiten dieselbe Definition von Seitenaufruf verwenden. Werkzeuge, die die Core Web Vitals erheben und berichten, behandeln bfcache-Wiederherstellungen als eigene Seitenbesuche in ihrem Datensatz (web.dev) - wer das nicht nachbaut, vergleicht Äpfel mit einer Teilmenge von Äpfeln.
Praktisch heißt das: Bevor Sie eine Abweichung als Defekt melden, prüfen Sie, ob beide Zahlen dieselben Navigationen umfassen. Chrome hat die Navigationstypen zusätzlich in CrUX aufgenommen, sodass sich die Zahl der bfcache-Navigationen auch ohne eigene Messung ablesen lässt (web.dev). Das ist der schnellste Gegencheck: Steht dort ein nennenswerter back_forward-Anteil und Ihre eigene Auswertung kennt keinen einzigen, liegt die Lücke bei Ihnen. Einen Startpunkt für die Messung der Kernkennzahlen liefert unser Core-Web-Vitals-Test.
Die Gegenrichtung ist genauso wichtig: Auch das Vorabladen verschiebt die Zahlen, nur nach oben statt nach unten. Wie sich Prerender-Treffer sauber trennen lassen, steht im Beitrag zu den Speculation Rules; für Anwendungen, die den Seitenwechsel im Browser selbst erledigen, gilt der Beitrag zur Soft Navigation. Auch dort hilft bfcache übrigens: Beim Zurückgehen in eine Single-Page-Anwendung erspart er die vollständige Neuinitialisierung der Anwendung von vorn (web.dev).
Prüfplan für Betreiber und Agenturen
Der Aufwand ist überschaubar, die Reihenfolge entscheidet. Erst messen, dann die Ursachen abräumen, dann erneut messen - sonst weiß hinterher niemand, welcher Schritt gewirkt hat und welcher nur zufällig mit einem Browser-Update zusammenfiel.
- Bestandsaufnahme: Zählt Ihr Messskript ein pageshow-Ereignis mit persisted gleich true? Wenn nicht, fehlt jede Wiederherstellung in Ihren Zahlen.
- Navigationstyp an jede Kennzahl hängen und die Auswertung nach navigate, reload, back_forward und prerender trennen.
- Den Zustand der Web Vitals bei jeder Wiederherstellung zurücksetzen, damit CLS und INP nicht doppelt in den Bericht wandern.
- unload-Listener suchen und durch pagehide ersetzen - auch in eingebundenen Fremdskripten, nicht nur im eigenen Code.
- Cache-Control: no-store auf die Seiten beschränken, die es wirklich brauchen, etwa Konto- und Kassenbereiche.
- notRestoredReasons auswerten und die häufigsten Gründe der Reihe nach abarbeiten.
- Den back_forward-Anteil vor und nach der Umstellung gegen die CrUX-Felddaten halten.
- Umstellungstag, alte und neue Zähldefinition schriftlich festhalten, damit der Sprung in den Zahlen später erklärbar bleibt.
Für Agenturen lohnt der letzte Punkt doppelt: Ein erklärter Sprung in den Zahlen ist kein Streitfall, ein unerklärter schon. Halten Sie Umstellungstag und Definitionswechsel im Messprotokoll der Website-Abnahme fest und prüfen Sie parallel, ob Ihre Felddaten überhaupt alle Browser abdecken - die Blindstelle bei iPhone-Nutzern wirkt auf die Verteilung ganz ähnlich wie die bfcache-Lücke.
Wer die Lücke nicht selbst schließen will, misst sie mit einem Werkzeug, das beide Ereignisse von Haus aus kennt. Die Cookieless Analytics von XICTRAQ zählen Wiederherstellungen als eigenen Navigationstyp, ohne Cookie und ohne Einwilligungsbanner, und die Core-Web-Vitals-Messung schreibt LCP, INP und CLS je Navigationstyp getrennt fort. Wie die Auswertung aufgebaut ist, zeigt die Analytics-Dokumentation; worin sich der Messverlust durch Inhaltsblocker davon unterscheidet, steht im Beitrag zu Adblocker-Verlusten in der First-Party-Messung. Teams, die mehrere Kundenprojekte nebeneinander betreuen, finden im Agenturzugang den passenden Rahmen dafür.
Dieser Beitrag stützt sich auf: web.dev, Back/forward cache (Stand 03.09.2026); web.dev, Why is CrUX data different from my RUM data? (Stand 17.12.2025); Chrome for Developers, Deprecating the unload event (Stand 14.07.2026); MDN Web Docs, Window: pageshow event (Stand 28.07.2026); MDN Web Docs, PerformanceNavigationTiming: notRestoredReasons (Stand 01.09.2026); MDN Web Docs, PerformanceNavigationTiming: type (Stand 09.09.2025). Alle Zahlen und wörtlich wiedergegebenen Aussagen stammen aus diesen Quellen; die Tieflinks sind im Beitrag hinterlegt.