Performance

stale-while-revalidate: come si configura e come si testa

Cosa fa davvero `stale-while-revalidate`, come si combina con `stale-if-error` e come verificare che il CDN stia servendo la versione vecchia mentre aggiorna quella nuova.

In sintesi

  • `stale-while-revalidate` serve la copia vecchia e aggiorna in background: l’utente non aspetta.
  • Non è una cache infinita: la finestra dichiarata è il tempo massimo in cui accetti la copia vecchia.
  • Non usarlo su risposte personalizzate, mutazioni o dati che devono essere esatti al secondo.

`stale-while-revalidate` (SWR) è una direttiva di `Cache-Control`: per N secondi dopo la scadenza, la copia vecchia può essere servita mentre una richiesta in background la aggiorna. L’utente vede subito qualcosa, il CDN lavora dopo.

La sintassi

Cache-Control: public, max-age=60, stale-while-revalidate=300

Significato: per 60 secondi la risposta è fresca; dal secondo 61 al 360 può essere servita la copia vecchia, mentre il CDN la rigenera. Dopo, la richiesta aspetta una risposta nuova.

SWR e stale-if-error non sono la stessa cosa

DirettivaQuando intervieneCosa rischia
stale-while-revalidateDopo la scadenza, con backend raggiungibileDati vecchi per la durata della finestra
stale-if-errorQuando il backend restituisce erroreMostrare dati vecchi durante un guasto
max-agePrima della scadenzaNessuno: è la finestra fresca
no-storeSemprePerdere ogni vantaggio della cache

Combinali solo se sai cosa stai promettendo: `max-age=60, stale-while-revalidate=300, stale-if-error=600` significa che un errore può prolungare la vita dei dati vecchi.

Dove ha senso

  • Liste di catalogo che cambiano lentamente.
  • Immagini e asset con URL versionati.
  • Risposte pubbliche e identiche per tutti.
  • Pagine marketing senza dati personali.

Dove non ha senso

  • Risposte con dati dell’utente o token.
  • Mutazioni e endpoint che cambiano stato.
  • Saldi o prezzi che devono essere esatti al minuto.
  • Risposte che dipendono da cookie o geolocalizzazione.

Come si testa

Non fidarti dell’header: guarda cosa risponde il bordo. Due richieste ravvicinate devono mostrare la stessa versione; dopo la finestra, la seconda può ancora mostrare la vecchia mentre il CDN rigenera.

curl -sI https://example.com/api/catalog | grep -i "cache-control\|age\|x-cache"
curl -sI https://example.com/api/catalog | grep -i "age\|x-cache"

Controlla `Age` e l’header del provider (`x-cache`, `cf-cache-status`). Se `Age` non cresce, il CDN non sta servendo dalla cache e la direttiva è solo decorativa.

Le liste pubbliche di EneUI usano una cache breve con finestra stale: il catalogo è pubblico, identico per tutti e cambia con i cicli di raccolta. Con 111.985 componenti (31 ottobre 2026) servire dalla cache non è un dettaglio: è ciò che tiene in piedi il sito su una macchina piccola.

Domande frequenti

SWR aggiorna la cache in background?

Sì, quando una richiesta arriva dopo la scadenza: serve la copia vecchia e avvia il refresh. Non c’è un job separato.

Posso usarlo su un’API con login?

No, se la risposta è personalizzata e il CDN è condiviso. Servire la risposta di un utente a un altro è un incidente, non un bug di performance.

Quanto deve durare la finestra?

Quanto il prodotto tollera dati vecchi. Non esiste un numero universale: dichiara la tolleranza e configura di conseguenza.

SWR vale anche per le immagini?

Sì, spesso tramite la CDN. Gli asset con URL versionati sono il caso più sicuro, perché il contenuto non cambia mai sotto lo stesso URL.

Come verifico che funzioni su Vercel o Cloudflare?

Guarda gli header di stato cache del provider e l’header `Age`. Se non compaiono, la direttiva non è stata applicata a quel percorso.