Cache back/forward (bfcache)

Che cos'è la cache back/forward, la funzione del browser che congela un'intera pagina in memoria per una navigazione Indietro/Avanti istantanea, come si distingue dalla cache HTTP, che cosa blocca l'idoneità, come testarla e qual è il suo rapporto reale e indiretto con Core Web Vitals e SEO.

Prima pubblicazione: 3 lug 2026 · Ultimo aggiornamento: 11 ago 2026 · Advanced
Lingue

La cache back/forward (bfcache) è un'ottimizzazione del browser che congela in memoria un'intera pagina — DOM, heap JavaScript e stato in esecuzione — quando lasci la pagina, così Indietro o Avanti possono ripristinarla all'istante senza ricaricamento, nuovo rendering o richieste di rete, finché il browser non espelle prima quell'istantanea. È una funzione del browser, non un fattore di ranking: la documentazione di Google sui Core Web Vitals non la menziona. Il rapporto con la SEO è indiretto e circoscritto: una navigazione ripristinata può produrre LCP quasi istantaneo e CLS praticamente nullo per gli utenti che la ricevono, migliorando i CWV di campo aggregati su siti con traffico Indietro/Avanti significativo (1 navigazione desktop su 10 e 1 mobile su 5), ma senza garantire tasso di ripristino, valutazione CWV complessiva, ranking o conversioni. Il principale blocco è il gestore unload; storicamente il maggiore era Cache-Control: no-store, anche se dal rollout 2025 Chrome consente condizionatamente la bfcache per molte pagine no-store. Testa con Chrome DevTools o diagnostica sul campo con l'API notRestoredReasons riservata a Chrome. Non confonderla con cache HTTP, cache delle risorse in memoria, Cache Storage di un service worker o la vecchia funzione di ricerca «cached page».

TL;DR — Il bfcache è un’istantanea in memoria dell’intera pagina (DOM + heap JS + stato in esecuzione), non una risposta HTTP recuperabile, la cache delle risorse nella memoria del browser o la Cache Storage di un service worker: questa è la distinzione concettuale numero 1 da fissare. Quando ti allontani, il browser mette in pausa JS e congela la pagina; con Indietro/Avanti, se l’istantanea congelata è ancora disponibile, la scongela e la ridisplaya istantaneamente senza richieste di rete, ma l’espulsione è sempre possibile: considera il ripristino probabile, non garantito. Non è un fattore di ranking Google documentato (i documenti Search Central sui Core Web Vitals non lo menzionano); la rilevanza è indiretta e circoscritta, attraverso la misurazione CWV di campo (soprattutto LCP e CLS) nelle navigazioni effettivamente ripristinate: non garantisce tasso di ripristino, punteggio CWV aggregato, ranking o conversioni. Il principale blocco all’idoneità è l’handler unload (circa 18 punti percentuali di tasso di utilizzo su Chrome); storicamente il maggiore era Cache-Control: no-store (bloccava circa il 17% delle navigazioni di cronologia mobile e il 7% di quelle desktop), anche se Chrome ora ammette condizionatamente molte pagine no-store (espulse al cambio di autenticazione/cookie e ancora bloccate dalle stesse API con connessioni aperte) dopo il rollout del 2025. Connessioni aperte, timer e observer vanno chiusi o messi in pausa su pagehide/freeze e ristabiliti su pageshow/resume; anche window.opener, policy delle permissions e frame possono bloccarlo: controlla la ragione per frame in DevTools o notRestoredReasons invece di supporre. Fai test una tantum con Chrome DevTools; diagnostica sul campo con l’API notRestoredReasons riservata a Chrome (un risultato null non prova un ripristino e il testo della ragione non è stabile). Ogni browser ha regole di idoneità proprie e le soft navigation delle SPA non ricevono lo stesso trattamento.

Evidence for this claim The back-forward cache stores a complete page snapshot for instant history navigation. Scope: Current official or standards documentation. Confidence: high · Verified: web.dev: Back/forward cache Evidence for this claim Browser eligibility rules and APIs such as unload handlers can prevent bfcache use. Scope: Current official or standards documentation. Confidence: high · Verified: web.dev: bfcache eligibility

Che cos’è davvero il bfcache (la spina dorsale dell’accuratezza)

La cosa più importante da dire correttamente è questa: il bfcache è un’istantanea in memoria dell’intera pagina, non una risposta HTTP memorizzata. Quando lasci una pagina, invece di smontarla il browser mette in pausa l’esecuzione JavaScript e congela tutto — DOM, heap JS, timer in volo e il resto — conservandolo in memoria. Se premi Indietro o Avanti mentre l’istantanea è ancora disponibile, il browser la scongela e ridisplaya esattamente la pagina che avevi lasciato, con zero richieste di rete e zero nuovo rendering. È un ripristino possibile, non garantito: il browser può espellere l’istantanea prima del ritorno (pressione sulla memoria, timeout, determinati eventi), oppure una regola specifica del browser può imporre un caricamento nuovo; in tal caso è una normale navigazione nella cronologia. La formulazione canonica di Google è che il bfcache è «a browser optimization that enables instant back and forward navigation.» (traduzione) «un’ottimizzazione del browser che consente una navigazione istantanea indietro e avanti.»

Ecco perché confonderlo con la cache HTTP/browser è l’errore ricorrente dei concorrenti. La cache HTTP conserva risposte a richieste precedenti, cioè file da riservire. Il bfcache conserva la pagina viva in esecuzione. La documentazione Chrome DevTools traccia esplicitamente il confine: il bfcache «differs from browser cache and HTTP cache.» (traduzione) «è diversa dalla cache del browser e dalla cache HTTP.» Non «attivi» il bfcache con gli header di caching come configuri la cache HTTP: l’unico punto in cui entrano gli header è che Cache-Control: no-store in passato squalificava una pagina (ne parleremo più avanti).

La stessa distinzione vale rispetto ad altre due cache che vengono confuse con il bfcache: la cache delle risorse nella memoria del browser (script compilati e immagini decodificate conservati per la sessione corrente) e la Cache Storage di un service worker (coppie richiesta/risposta esplicite che il sito gestisce con caches.open()). Entrambe possono essere attive contemporaneamente al bfcache sulla stessa pagina, ma nessuna delle due è il bfcache, che è nello specifico l’istanza di pagina congelata, non asset memorizzati o risposte intercettate.

Un’altra distinzione è utile perché continua a generare confusione: il bfcache non ha nulla a che fare con la vecchia funzione di ricerca «pagina memorizzata» che Google (e Bing) mostravano un tempo nei risultati. Era un’istantanea archiviata di una pagina nell’indice di ricerca ed è stata ritirata. Il bfcache è una funzione del motore di rendering lato client.

Quanto sono comuni davvero le navigazioni Indietro/Avanti?

Non è un caso limite. Secondo web.dev, «1 in 10 navigations on desktop and 1 in 5 on mobile are either back or forward.» (traduzione) «una navigazione desktop su 10 e una mobile su 5 è una navigazione indietro o avanti.» Su qualunque sito con flussi di ritorno — categoria-prodotto e ritorno nell’ecommerce, risultati di ricerca, contenuti paginati, lettura articolo-dopo-articolo — è una fetta consistente di navigazioni reali che puoi rendere quasi istantanee.

Supporto dei browser

«All major browsers include a bfcache, including Chrome since version 96, Firefox and Safari.» (traduzione) «tutti i principali browser includono una bfcache, compresi Chrome dalla versione 96, Firefox e Safari.» Firefox e Safari hanno implementazioni bfcache proprie e più longeve; tutti i browser basati su Chromium (Edge, Brave, Opera, Arc) ereditano quella di Chrome. La documentazione delle policy Edge di Microsoft descrive la stessa funzione: quando si lascia una pagina, il suo stato corrente (albero del documento, script e così via) può essere conservato nella back-forward cache e, se il browser torna indietro, la pagina può essere ripristinata e mostrata nello stato in cui si trovava prima di essere memorizzata. È abilitata di default in Edge; l’unico interruttore è una policy aziendale controllata dall’amministratore IT, non dal proprietario del sito.

La precisazione importante: il bfcache di ogni browser applica regole di idoneità proprie. Una pagina che supera «Test back/forward cache» in Chrome DevTools non è garantita come idonea in Firefox o Safari. Considera il passaggio Chrome necessario, non sufficiente.

Che cosa blocca l’idoneità al bfcache

L’evento unload — il blocco principale

Se ricordi una sola cosa di questo articolo: smetti di usare l’evento unload. web.dev lo sottolinea con rara enfasi per un documento Google: «Never use the unload event. Ever!» (traduzione) «non usare mai l’evento unload. Mai!» Su Chrome, gli handler unload costano circa una riduzione di 18 punti percentuali del tasso di utilizzo del bfcache, di gran lunga la più grande esclusione auto-inflitta.

Chrome lo sta deprecando attivamente per due ragioni. Primo, è il maggiore blocco al bfcache. Secondo, unload è estremamente inaffidabile in partenza: sui dispositivi mobili spesso non viene eseguito perché le schede passano in background e vengono terminate e il browser privilegia il bfcache rispetto all’esecuzione di unload. Quindi l’evento su cui fai affidamento per la «pulizia» spesso non viene eseguito e blocca un vero vantaggio prestazionale.

Le correzioni:

  • Sostituisci unload con pagehide. L’evento pagehide si verifica in ogni caso in cui si verificherebbe unload, più quando una pagina entra nel bfcache: è quindi un miglioramento netto. Usa visibilitychange per una pulizia affidabile quando «l’utente se ne va».
  • Rileva un ripristino bfcache con pageshow. Ascolta pageshow e controlla event.persisted: se è true, la pagina è stata ripristinata dal bfcache; è il momento di aggiornare dati obsoleti o ricontare una visualizzazione.
  • Blocca in modo proattivo gli ascoltatori unload con l’header di risposta Permissions-Policy: unload=(), che impedisce del tutto la registrazione degli handler unload. Chrome sta spostando gradualmente la policy predefinita verso deny (una Permissions-Policy per unload è stata rilasciata da Chrome 115).

Cache-Control: no-store — storicamente il blocco più grande, oggi più sfumato

È il punto sulla freschezza che la maggior parte dei contenuti concorrenti sbaglia. Storicamente, Cache-Control: no-store era la singola ragione principale per cui le pagine venivano escluse dal bfcache: le cifre Chrome lo stimavano in circa 17% delle navigazioni nella cronologia mobile e 7% di quelle desktop. Molti siti impostano no-store in modo difensivo per non servire una pagina obsoleta, ma l’argomento Google è che un ripristino bfcache non carica una risposta cache obsoleta: ridisplaya la pagina viva esatta, quasi come se la scheda fosse rimasta aperta.

Chrome ha quindi cambiato il comportamento, ma in modo condizionale, non universale. Gli esperimenti sono iniziati in Chrome 116, con il rollout finale al 100% degli utenti tra marzo e aprile 2025: ora Chrome ammette molte pagine no-store nel bfcache, soggette a condizioni di sicurezza specifiche invece che a un’eccezione generale. Secondo la documentazione Chrome, esistono vincoli reali: la pagina viene espulsa dal bfcache se cambiano lo stato di autenticazione o i cookie mentre è congelata (così un visitatore disconnesso o con cookie cancellati non vede un’istantanea autenticata obsoleta) e un elenco fisso di API — le stesse API per connessioni aperte descritte sotto (IndexedDB, WebSocket, WebRTC e le altre) — continua a escludere una pagina no-store dal bfcache come qualunque altra pagina. È un comportamento specifico di Chrome in un intervallo di versioni preciso, non una regola da presumere per gli altri browser o per versioni Chrome più vecchie: recupera il report DevTools/notRestoredReasons corrente per browser e versione che stai testando invece di fidarti di una regola fissa. La conseguenza pratica: qualsiasi guida (comprese le versioni vecchie di questa) che elenchi no-store come blocco incondizionato e permanente al bfcache è obsoleta, ma lo è anche trattarlo come completamente risolto. Se la freschezza conta davvero, la documentazione Chrome suggerisce no-cache o un max-age breve (per esempio max-age=60) invece di no-store.

Connessioni aperte, observer e altri blocchi

Al momento della navigazione, alcune risorse aperte possono ancora bloccare l’idoneità, e proprio quali lo facciano — e se blocchino del tutto o vengano solo chiuse e ricollegabili — dipende dal browser e dalla versione. Considera l’elenco sotto come esempi di un modello, non come una lista fissa e permanente.

  • Richieste fetch() / XMLHttpRequest in corso.
  • Transazioni IndexedDB aperte.
  • Connessioni WebSocket / WebRTC, timer e observer aperti (MutationObserver, IntersectionObserver e simili). È un’area in evoluzione: le note di rilascio recenti di Microsoft Edge mostrano che un WebSocket aperto ora viene chiuso quando la pagina entra nel bfcache (invece di bloccare la cache del tutto), con riconnessione raccomandata tramite l’evento pageshow e il controllo di event.persisted. Questo rispecchia la tendenza più ampia di Chrome a ridurre i blocchi invece di escludere semplicemente le pagine.

Il modello generale da implementare, invece di imparare a memoria una lista fissa: chiudi o metti in pausa connessioni aperte, timer e observer nella gestione pagehide/freeze e ristabiliscili nella gestione pageshow/resume quando event.persisted è true. Questo modello resta valido anche se un browser cambia quali API bloccano del tutto l’idoneità e quali invece sospende lasciando che tu ti ricolleghi.

window.opener, policy delle permissions e frame. Un riferimento window.opener, alcune policy delle permissions e iframe incorporati (della stessa origine o di origine diversa) possono influire sull’idoneità: è quanto compare nella checklist che ho ricavato dalla guida CLS di Ahrefs e nella documentazione Chrome. Non presumere però la causa reale da una checklist generica: il pannello DevTools e l’API notRestoredReasons riportano le ragioni di blocco per frame, per il frame principale e per ogni iframe, perché il frame responsabile non è sempre la pagina di livello superiore. Recupera la ragione reale dal report per frame del browser che stai testando invece di indovinare da un elenco generale.

Ottenere correttamente la sequenza evento/stato del ciclo di vita

Confondere ciò che ogni evento del ciclo di vita prova con ciò che si limita a suggerire è il secondo bug di correttezza più comune qui, dopo gli errori di idoneità già descritti:

Evento / statoSegnaleChe cosa significa davveroChe cosa fare
pagehide (event.persisted === true)Intento di memorizzareIl browser sta tentando di congelare la pagina per il bfcache, non è una voce di cache confermataChiudi/metti in pausa connessioni, timer e observer qui; non presumere che la pagina venga davvero ripristinata
freezeIn pausaL’esecuzione JS è in pausa; la pagina può ancora essere espulsa prima di un ripristinoNessuna azione oltre a quella già fatta su pagehide
(nessun evento) possibile espulsioneIl browser può eliminare una pagina congelata dalla memoria in qualsiasi momento — pressione sulla memoria, timeout, regola del browser — e non esiste un evento che venga eseguito per questoNon fare affidamento su codice di pulizia eseguito in seguito; eseguilo incondizionatamente su pagehide/freeze
pageshow (event.persisted === true)Ripristino confermatoL’unico segnale affidabile che un ripristino bfcache è davvero avvenutoAggiorna stato sensibile al tempo, ricollega le connessioni chiuse, conta esattamente una visualizzazione analytics
resumeRipresaL’esecuzione JS riprende dopo un ripristino confermatoRicollega ciò che era stato messo in pausa su freeze

La regola pratica: tratta pagehide.persisted come intento, non come prova: la pagina può essere espulsa prima che tu veda un ripristino. Solo pageshow.persisted === true dimostra che un ripristino è avvenuto. Esegui la pulizia incondizionatamente su pagehide/freeze (è economico e sicuro anche in una normale navigazione) e svolgi il lavoro specifico del ripristino solo su pageshow/resume, condizionato da event.persisted, così non aggiorni dati e non conti due volte una visualizzazione analytics in un semplice caricamento nuovo.

Come testare e diagnosticare il bfcache

Laboratorio / una tantum: Chrome DevTools

Apri DevTools → Application → Background services → Back/forward cache, poi fai clic su «Test back/forward cache.» (traduzione) «Testa la cache back/forward.» Chrome naviga automaticamente a chrome://terms/ e torna indietro, quindi segnala successo o un elenco specifico delle ragioni di blocco. È utile per controllare un URL alla volta.

Campo / produzione: API notRestoredReasons

In passato l’unico modo per controllare l’idoneità era il test DevTools manuale, un URL alla volta: non c’era modo di capire perché le navigazioni degli utenti reali fossero bloccate. La proprietà notRestoredReasons di PerformanceNavigationTiming (rilasciata in Chrome 123+) colma il divario: segnala le ragioni specifiche di blocco per il frame principale e gli iframe della stessa origine nei dati reali di campo.

const nav = performance.getEntriesByType('navigation')[0];
console.log(nav.notRestoredReasons);

Ecco alcune cose da fare correttamente, direttamente dalle indicazioni API di Chrome:

  • È solo Chrome (123+). Firefox e Safari non espongono un’API di campo equivalente, quindi per conoscere il tasso di ripristino devi ancora fare controlli manuali in quei browser.
  • Un risultato null è ambiguo, non un semaforo verde. Può significare che la pagina è stata ripristinata oppure che il browser non ha raccolto una ragione; la documentazione Chrome dice di non trattare null come prova di un ripristino riuscito.
  • Il testo della ragione non è un contratto stabile. Non codificare corrispondenze di stringhe; raggruppa e osserva le tendenze per ragione, perché la formulazione esatta può cambiare tra versioni Chrome.

In pratica: raccogli notRestoredReasons insieme ai tassi di ripristino pageshow.persisted prima e dopo il rilascio di una correzione, confronta la tendenza invece di una singola istantanea e abbinala a un passaggio manuale DevTools/lab in Firefox e Safari per i browser che l’API non può raggiungere. È lo strumento da usare per diagnosticare il bfcache su larga scala in RUM/produzione invece di controllare gli URL uno per uno, ma non trattarlo come il quadro completo.

Bfcache e Core Web Vitals — il rapporto preciso

Ecco la sfumatura che la maggior parte dei contenuti concorrenti appiattisce e l’angolo che vale la pena presidiare.

Come si misura un ripristino bfcache. I browser (e quindi i dati di campo CrUX) contano una navigazione ripristinata dal bfcache come un «caricamento pagina» estremamente rapido: LCP quasi istantaneo e, quando la pagina è implementata correttamente (nulla deve ricalcolare il layout), zero CLS aggiuntivo in pratica, perché non c’è nuovo rendering. Nel confronto reale di DebugBear, una pagina ripristinata dal bfcache ha ottenuto un LCP di circa 100ms contro ~427ms per un caricamento non in cache. È esattamente il motivo per cui il bfcache appare come leva per CLS e LCP nella mia checklist CLS di Ahrefs, dove lo riassumo così: «Make sure your pages are eligible for bfcache. The back/forward cache keeps pages in the browser cache. It allows for instant loading of a page that was already loaded, meaning no layout shifts will happen.» (traduzione) «Assicurati che le pagine siano idonee alla bfcache. La cache back/forward conserva le pagine nella cache del browser e permette di caricare istantaneamente una pagina già caricata, evitando variazioni del layout.»

Due precisazioni di ambito meritano accuratezza, perché è qui che i contenuti concorrenti tendono a esagerare. Primo: l’effetto riguarda solo le navigazioni che CrUX classifica come Indietro/Avanti (la dimensione navigation-type); non dice nulla sulle navigazioni di prima visita o sui ricaricamenti, che sono la maggior parte del traffico su molti siti. Secondo: un ripristino che migliora l’esperienza misurata per gli utenti che lo ricevono non equivale a una garanzia: chi viene espulso dalla bfcache (vedi la tabella del ciclo di vita) ottiene comunque un caricamento normale e non migliorato, quindi il lavoro sull’idoneità della bfcache sposta il tasso di ripristino tra le navigazioni Indietro/Avanti, non una quota fissa del traffico totale — e non garantisce la valutazione aggregata dei Core Web Vitals di campo, il ranking o il tasso di conversione. È una leva reale e misurabile con un ambito preciso e limitato, non una correzione generale delle prestazioni o della SEO.

Il bfcache è un fattore di ranking? No. Questa è l’affermazione difendibile e distintiva. La documentazione Google sul ranking dei Core Web Vitals non menziona affatto il bfcache. La catena onesta è: idoneità bfcache → numeri CWV di campo migliori (soprattutto LCP/CLS) nelle navigazioni Indietro/Avanti → i Core Web Vitals sono uno dei molti segnali di «esperienza di pagina» che Google dice essere allineati a ciò che i suoi sistemi di ranking già premiano. È un’affermazione molto più debole e precisa di «il bfcache aumenta il ranking»: ed è quella che i contenuti concorrenti dovrebbero fare, ma di solito non formulano con cura. Il bfcache è inoltre, correttamente, una funzione del motore di rendering, non del crawler: non riguarda il modo in cui Googlebot o Bingbot eseguono il crawl delle pagine, perciò non esiste una «posizione di Bing sul bfcache per la SEO» analoga a quella su robots.txt o sitemap.

SPA e soft navigation. Il bfcache opera sulle navigazioni reali del browser e sugli eventi della cronologia. Il cambio di rotta «soft» lato client di una single-page app (uno scambio di vista guidato da JS che non attiva una navigazione reale del browser) non è un evento bfcache e non riceve lo stesso trattamento. I tentativi di alcuni strumenti RUM di attribuire i Core Web Vitals alle soft navigation possono creare discrepanze di misurazione tra CrUX e RUM: un punto da segnalare se stai verificando un sito basato su un framework JS.

Quanto sono diffusi i blocchi al bfcache nel mondo reale?

Il Web Almanac di HTTP Archive tiene traccia del fenomeno, che è vivo e in movimento, non una notizia vecchia ormai definita. Nell’edizione 2022 almeno il ~22% delle pagine mobile non era idoneo al bfcache solo per i criteri unload e no-store. Da allora l’uso degli handler unload è diminuito nelle diverse fasce di siti e dispositivi, ma l’uso di Cache-Control: no-store è aumentato (il capitolo 2025 lo colloca intorno al 23% dei siti, rispetto a circa il ~21% nel 2024, in parte per l’aumento delle esperienze autenticate/personalizzate e per requisiti di conformità più severi).

La scoperta controintuitiva da citare: i siti più grandi e con più traffico sono sproporzionatamente più propensi a bloccare il proprio bfcache. Tra i primi 1 000 siti, circa il 28% delle pagine desktop e il 20% di quelle mobile usa ancora handler unload, contro solo ~11% desktop / ~10% mobile su tutti i siti, spesso perché i siti più grandi portano più codice legacy di analytics e dipendente da unload. I siti che hanno più traffico Indietro/Avanti da perdere sono spesso quelli che continuano a ostacolarsi da soli.

Dove si colloca

Il bfcache è una leva di performance tra diverse in questo cluster. Il suo vantaggio si vede nei dati di campo dei Core Web Vitals, in particolare in Cumulative Layout Shift e Largest Contentful Paint, perché una pagina ripristinata viene ridisplayata istantaneamente senza ricalcolo del layout. È distinto dalla caching, che conserva file invece di un’istantanea di pagina viva, anche se le due cose condividono l’header Cache-Control come punto di contatto. Non esiste un legame diretto con Interaction to Next Paint, quindi non ne forzerò uno.

Add an expert note

Pin an expert quote

New person? Create their unclaimed profile at /admin/experts/ → Pin a quote first.