Cache CDN edge: Cloudflare vs cache del hosting, quale scegliere e perché

Tutti parlano di CDN, ma pochi distinguono tra cache CDN edge e cache del hosting. La differenza è decisiva per le prestazioni: Cloudflare cachea HTML, il tuo hosting PHP cachea le query. Capire quale serve e quando.
La confusione più diffusa sul caching è tra CDN e cache del hosting. 'Ho Cloudflare, quindi il sito è in cache' — no, non è così semplice. Cloudflare cachea gli asset statici (CSS, JS, immagini) ai bordi della rete globale, e può cacheare anche l'HTML se lo configuri esplicitamente. La cache del hosting (FastCGI, page cache lato server) cachea l'output PHP generato. Sono due livelli diversi che fanno cose diverse, e usarli male significa o non sfruttare la CDN per il suo scopo principale, o cacheare pagine dinamiche che non dovrebbero essere cachate (carrello, checkout, account).
Il principio è: la CDN cachea per posizione geografica (latenza), la cache del hosting cachea per calcolo (PHP+database). La prima serve se hai visitatori geograficamente distribuiti: un utente in Australia che visita un server a Francoforte ha 250ms di latenza di rete solo per arrivare al server. La CDN edge riduce quella latenza a 20ms servendo la copia del sito dal data center di Singapore. La cache del hosting invece non risolve la latenza geografica — ma risolve il costo del calcolo PHP a ogni visita. Se hai un sito lento perché ogni pagina richiede 800ms di PHP, la cache del hosting è la soluzione; se hai un sito veloce ma lontano, la CDN è la soluzione. Spesso servono entrambe, in cascata.
Cloudflare: cosa cachea e cosa non cachea di default
Cloudflare di default cachea solo gli asset statici con estensioni note (CSS, JS, immagini, font). Non cachea l'HTML di default — l'HTML passa sempre attraverso Cloudflare fino all'origine. Per cacheare l'HTML sulla CDN edge devi creare delle Page Rules o usare Cache Rules esplicite. Il caso d'uso classico è cacheare la home, le pagine pubbliche e gli articoli del blog, escludendo il carrello, il checkout, l'area account e tutte le pagine dinamiche:
# Cloudflare — Page Rules per cacheare l'HTML pubblico
# (da configurare nel dashboard Cloudflare o via API)
# Regola 1: cachea tutte le pagine statiche pubbliche
# URL: *miosito.com/*
# Setting: Cache Level = Cache Everything
# Edge Cache TTL: 1 ora (3600 secondi)
# Browser Cache TTL: 30 minuti
# Regola 2: bypassa la cache per pagine dinamiche
# URL: *miosito.com/carrello* , *miosito.com/checkout* , *miosito.com/mio-account* , *miosito.com/wp-admin*
# Setting: Cache Level = Bypass
# Via API (curl):
curl -X POST "https://api.cloudflare.com/client/v4/zones/{zone_id}/pagerules" \
-H "Authorization: Bearer {token}" \
-H "Content-Type: application/json" \
--data '{
"targets": [{"target": "url", "constraint": {"operator": "matches", "value": "*miosito.com/carrello*"}}],
"actions": [{"id": "cache_level", "value": "bypass"}],
"priority": 1,
"status": "active"
}'Cache del hosting: cosa risolve davvero
La cache del hosting (FastCGI cache su Nginx, o plugin come WP Rocket, W3 Total Cache) cachea l'output HTML generato da PHP. Se una pagina richiede 800ms di calcolo PHP+database per essere generata, la cache la serve in 5ms senza toccare PHP. La latenza geografica però resta identica — un utente lontano ha sempre la latenza di rete per arrivare al server. La cache del hosting risolve il costo di calcolo, non la latenza geografica.
Il punto decisivo è che le due cache vanno configurate per non sovrapporsi in modo sbagliato. Se il tuo hosting ha una cache FastCGI attiva e Cloudflare cachea anche l'HTML, hai due cache in cascata: Cloudflare edge (per la latenza) → cache del hosting (per il calcolo). Quando una pagina cambia (pubblichi un articolo), Cloudflare la vede vecchia e va all'origine, dove la cache del hosting la serve dalla sua cache interna. Risultato: l'utente vede la versione vecchia fino alla scadenza del TTL di Cloudflare. Per evitarlo, devi svuotare entrambe le cache quando pubblichi, o configurare un purge webhook:
// Purge cache Cloudflare + hosting quando un contenuto viene pubblicato/modificato
add_action( 'save_post', function( $post_id ) {
if ( wp_is_post_revision( $post_id ) || get_post_status( $post_id ) !== 'publish' ) {
return;
}
// 1. Purge cache del hosting (se supportato via API interna o plugin)
if ( function_exists( 'rocket_clean_post' ) ) {
rocket_clean_post( $post_id );
}
// 2. Purge cache Cloudflare via API
$zone_id = getenv( 'CLOUDFLARE_ZONE_ID' );
$api_token = getenv( 'CLOUDFLARE_API_TOKEN' );
$post_url = get_permalink( $post_id );
wp_remote_post( "https://api.cloudflare.com/client/v4/zones/{$zone_id}/purge_cache", array(
'headers' => array(
'Authorization' => 'Bearer ' . $api_token,
'Content-Type' => 'application/json',
),
'body' => json_encode( array(
'files' => array( $post_url, home_url( '/' ) ), // purge articolo + home
) ),
'timeout' => 10,
) );
}, 10, 1 );WooCommerce: il caso in cui sbagliare rompe tutto
Il caso critico è WooCommerce. Se Cloudflare cachea il carrello per sbaglio (regola Cache Everything troppo generica), l'utente A vede il carrello dell'utente B. Se la cache del hosting cachea la pagina di checkout, l'utente vede vecchi totali o dati di altri ordini. Le esclusioni devono essere sia a livello Cloudflare (Page Rule bypass) sia a livello hosting (cookie del carrello o URL pattern). Il controllo incrociato è la prassi:
# Verifica che le pagine dinamiche NON siano in cache
# Cloudflare: X-Cache-Status deve essere BYPASS
for path in '/carrello/' '/checkout/' '/mio-account/'; do
echo -n "$path: "
curl -sI "https://miosito.com${path}" | grep -i 'cf-cache-status'
done
# Output atteso (tutte BYPASS):
# /carrello/: cf-cache-status: BYPASS
# /checkout/: cf-cache-status: BYPASS
# /mio-account/: cf-cache-status: BYPASS
# Verifica che le pagine statiche SIANO in cache
for path in '/' '/chi-siamo/' '/contatti/'; do
echo -n "$path: "
curl -sI "https://miosito.com${path}" | grep -i 'cf-cache-status'
done
# Output atteso (tutte HIT o MISS con header age > 0):
# /: cf-cache-status: HIT
# /chi-siamo/: cf-cache-status: HIT
# /contatti/: cf-cache-status: HITQuando serve solo una delle due (e quando servono entrambe)
Non ogni sito ha bisogno di entrambe. Un sito vetrina con traffico tutto italiano su un hosting a Milano non ha bisogno di Cloudflare per la latenza — la cache del hosting basta. Un e-commerce con clienti in tutta Europa su un server a Francoforte ha bisogno di Cloudflare per la latenza ma anche di cache del hosting per il costo di calcolo. Un portale editoriale ad alto traffico globale ha bisogno di entrambe, in cascata, con purge coordinato. La regola pratica è: misura prima, installa poi. Se il field data di PageSpeed mostra latenza elevata tra utente e server, serve la CDN; se mostra costo di calcolo elevato (LCP lento anche su server vicino), serve cache del hosting; se mostra entrambi, servono entrambe.
Un audit che misura LCP, TTFB e latenza geografica reale è il modo più rapido di capire quale cache serve al tuo caso, evitando di installare Cloudflare 'perché sì' su un sito che non ne trae vantaggio, o di non usarlo su un sito che ne avrebbe disperatamente bisogno. Le due cache non sono alternative, sono complementari — ma vanno scelte in base ai dati del traffico reale, non al sentito dire.
Misura TTFB, latenza e dove serve la cache per il tuo traffico reale.
Un check-up misura latenza geografica, TTFB e Core Web Vitals sugli utenti reali per capire quale cache serve: CDN edge per la latenza, cache del hosting per il calcolo, o entrambe in cascata.
Articoli correlati

WordPress Multisite: pro, contro e quando NON conviene (anche per le agenzie)
Leggi
Log server e errori 502/503: leggere i log Nginx prima di aprire un ticket
Leggi
