Font, librerie, icone: caricarli da una CDN pubblica è la scelta predefinita di moltissimi siti, ed è comoda. Vale però la pena rifare i conti, perché la ragione tecnica principale per cui quella scelta era vantaggiosa è venuta meno alcuni anni fa e la maggior parte dei consigli in circolazione non se ne è accorta.

Il vantaggio che non c'è più#

partizionamento della cache
L'argomento storico a favore della CDN condivisa:  "Il visitatore ha già scaricato jQuery da quel CDN su un altro sito,   quindi ce l'ha in cache e il tuo sito parte istantaneo."Era vero. Non lo è più dal 2020, quando i browser hanno introdotto ilPARTIZIONAMENTO della cache HTTP: ogni sito ha la propria partizione,e la stessa risorsa scaricata da esempio.it e da altro.it è memorizzataDUE volte, in due compartimenti separati.Il motivo è la privacy: una cache condivisa fra siti è un canalelaterale. Misurando il tempo di caricamento di una risorsa si deducevase il visitatore l'avesse già scaricata, e quindi se avesse visitatoun certo sito — un metodo di tracciamento senza cookie.Firefox: partizionamento dal 2021 (Total Cookie Protection)Chrome:  dal 2020 (cache partitioning)Safari:  dal 2013, primo ad adottarloConseguenza pratica: usando una CDN pubblica oggi si paga unaconnessione a un host in più e NON si guadagna la cache condivisa.Il vantaggio principale è semplicemente scomparso.

La motivazione del cambiamento è interessante di per sé: una cache condivisa fra siti diversi era un canale laterale sfruttabile. Misurando quanto ci metteva a caricare una risorsa, una pagina poteva dedurre se il visitatore l'avesse già scaricata altrove — e quindi ricostruire parte della sua cronologia, senza cookie e senza consenso. I browser hanno chiuso il canale partizionando la cache, e con esso è sparito il beneficio della CDN condivisa.

Quanto costa un dominio in più#

il costo di apertura
Che cosa costa davvero un dominio in più, prima ancora che arriviun byte utile:  esempio.it (già connesso)          cdn.esterno.com (da zero)  ────────────────────────           ────────────────────────────  richiesta ──▶                      DNS       ~20-120 ms                                     TCP       1 RTT                                     TLS       1-2 RTT                                     richiesta ──▶                                     ────────────────────────────                                     ~100-300 ms su rete mobile                                     PRIMA di scaricare qualsiasi cosaCon più domini esterni il costo non si somma soltanto: le connessionicompetono per la banda proprio nel momento più delicato, quando ilbrowser sta cercando di dipingere la prima schermata.

Su fibra la differenza è di poche decine di millisecondi e si può ignorare. Su rete mobile, dove il tempo di andata e ritorno sta fra i 40 e i 70 millisecondi, tre round-trip prima di ricevere un byte diventano un ritardo percepibile — e cade proprio nella finestra in cui il browser sta cercando di dipingere la prima schermata, cioè dove si misura il Largest Contentful Paint.

Che cosa resta a favore della CDN#

Sarebbe disonesto liquidarla: ci sono casi in cui è ancora la scelta giusta, e sono casi precisi.

SituazioneSceltaPerché
Font, icone, librerie di un sito normaleself-hostingla cache condivisa non esiste più; si risparmia una connessione
Immagini e video pesanti, pubblico globaleCDNla distanza fisica conta davvero sui megabyte
Traffico molto sbilanciato o imprevedibileCDNassorbe i picchi senza dimensionare il proprio server
Sito servito da una sola macchina in Europa, pubblico europeoself-hostingla latenza aggiuntiva è nell'ordine dei millisecondi
Prototipo, esperimento, pagina usa e gettaCDNla comodità vale più di tutto il resto
Sito soggetto a GDPR con utenti europeiself-hostingnessun dato personale trasferito a terzi

La distinzione utile è fra CDN come rete di distribuzione — che serve quando avete megabyte da consegnare lontano, e resta preziosa — e CDN pubblica di librerie, che era una scorciatoia il cui vantaggio principale è scaduto.

Se la CDN resta, almeno verificate cosa arriva#

sri.htmlHTML
<!-- Se una CDN pubblica serve davvero, almeno non fidatevi ciecamente.     Subresource Integrity: il browser calcola l'hash del file scaricato     e lo confronta. Se non corrisponde, non lo esegue. --><script src="https://cdn.esempio.com/lib@3.4.1/lib.min.js"        integrity="sha384-oqVuAfXRKap7fdgcCY5uykM6+R9GqQ8K/uxy9rx7HNQlGYl1kPzQho1wx4JwY8wC"        crossorigin="anonymous"></script><!-- Attenzione a cosa protegge e cosa no:     ✓ protegge da: CDN compromessa, file sostituito, attacco alla catena     ✗ NON protegge da: il file non arriva affatto (SRI lo blocca e basta,       il vostro sito resta senza quella libreria)     ✗ NON protegge la privacy: l'IP del visitatore è già stato trasmesso       nel momento in cui la richiesta è partita -->

Subresource Integrity fa una cosa sola e la fa bene: il browser calcola l'impronta del file ricevuto e lo esegue solo se corrisponde a quella dichiarata. Chiude lo scenario in cui la CDN viene compromessa e serve un file diverso.

Va però capito cosa non fa. Non protegge la privacy: nel momento in cui la richiesta parte, l'indirizzo IP del visitatore è già stato comunicato al terzo — che è precisamente il problema affrontato nell'articolo su cookie e GDPR. E non protegge la disponibilità: se il file non corrisponde, il browser lo blocca, e il vostro sito resta semplicemente senza quella libreria.

Il rischio che pesa di più#

terze-parti.jsJavaScript
// Il punto che rende la scelta meno "tecnica" di quanto sembri: ogni// dominio esterno è codice di qualcun altro che gira sulla vostra pagina,// con i vostri stessi privilegi.//// Uno script da CDN puo'://   - leggere il DOM, quindi i moduli che l'utente sta compilando//   - leggere document.cookie, se i cookie non sono HttpOnly//   - fare richieste con le credenziali del visitatore//   - modificare la pagina in qualunque modo//// Non è teoria: gli attacchi alla catena di distribuzione — un pacchetto// popolare compromesso, un dominio di CDN scaduto e ricomprato — colpiscono// tutti i siti che lo includono, contemporaneamente.//// Una CSP restrittiva è la difesa che vale la pena avere in ogni caso:"script-src 'self'"     // e la domanda "posso scrivere questa riga?"                        // diventa il test di quanto siete indipendenti

Uno script incluso da un dominio esterno non è «una risorsa»: è codice che gira dentro la vostra pagina con i vostri stessi privilegi. Può leggere il modulo che l'utente sta compilando, i cookie non marcati HttpOnly, e fare richieste autenticate per conto suo. Gli attacchi alla catena di distribuzione — un pacchetto popolare compromesso, un dominio scaduto e ricomprato da qualcun altro — colpiscono simultaneamente tutti i siti che lo includono.

Le tre responsabilità che tornano a voi#

Il self-hosting non è gratis, e vale la pena essere espliciti su cosa comporta.

1. La compressione#

CaddyfileConfig
# Le responsabilità che il self-hosting sposta su di voi. La prima è la# compressione: una CDN la fa da sola, il vostro server va configurato.# zstd batte gzip su rapporto e velocità; l'ordine dichiara la preferenza.www.esempio.it {    encode zstd gzip    reverse_proxy localhost:3000}# La verifica: senza l'intestazione, curl chiede la versione NON compressa# e sembra che la compressione non ci sia.#   curl -sI -H 'Accept-Encoding: zstd, gzip, br' https://esempio.it/css-build/app.css

Una CDN comprime da sola; il vostro server va configurato. È una riga, ma se manca si servono file due o tre volte più pesanti del necessario — e nessuno se ne accorge, perché il sito funziona.

2. Gli header di cache#

Anche questa è una configurazione da fare una volta, ed è trattata in dettaglio in cache busting: asset versionati con validità lunga e immutable, documento HTML con no-cache. Sbagliarla vanifica buona parte del guadagno di prestazioni per cui si era scelto il self-hosting.

3. Gli aggiornamenti#

manutenzione
# Seconda responsabilità: gli aggiornamenti di sicurezza non arrivano# piu' da soli. Vanno cercati, e il controllo va messo in calendario.npm auditfound 0 vulnerabilitiesnpm outdatedPackage   Current  Wanted  Latestesbuild   0.28.2   0.28.4  0.29.1# E i file copiati a mano in public/vendor non li vede nessuno strumento:# vanno annotati da qualche parte, con versione e provenienza.cat public/vendor/PROVENIENZA.mdgsap.min.js   3.12.5   da node_modules/gsap/dist/   aggiornato 2026-06-13
I file copiati a mano non li vede nessuno strumento: una nota con versione e provenienza accanto ai file è il minimo per non ritrovarsi fra due anni con una libreria di origine ignota.

È la responsabilità che si sottovaluta di più. Una libreria da CDN si aggiorna da sola quando cambiate il numero di versione nell'URL — o, peggio, quando puntate a @latest e si aggiorna senza che ve ne accorgiate. Una copia locale resta ferma finché non ci mettete mano voi. Va messo in calendario, e ha senso ricordare che «ferma» è anche una proprietà positiva: il vostro sito non cambia comportamento da solo alle tre di notte.

copia in casaShell
$ # Portare in casa le dipendenze: si copiano dal pacchetto installato,$ # con la versione bloccata dal lockfile. Nessun download a runtime.$ npm ci$ mkdir -p public/vendor$ cp node_modules/gsap/dist/gsap.min.js public/vendor/$ # Con il file in repository, il deploy non dipende piu' da nessun servizio$ # esterno: se il fornitore va giu' alle tre di notte, il sito funziona.

Il conto finale#

Per un sito come questo — servito da una macchina in Europa, con pubblico italiano, senza asset pesanti — il self-hosting vince su tutte le voci: nessun trasferimento di dati a terzi, nessuna connessione aggiuntiva, nessuna dipendenza da un servizio che può rallentare o sparire, e la possibilità di scrivere una CSP che consente solo il proprio dominio.

Il costo è mezz'ora di configurazione, fatta una volta, e un promemoria trimestrale per gli aggiornamenti. Quando il progetto cresce fino ad avere gigabyte di media e un pubblico su tre continenti, la CDN torna a essere la risposta giusta — per quei file, che è un problema diverso da quello di caricare un font.