# HTTP sulle decadi: una storia di fisica, latenza e adattamento grudging

<!--category-- HTTP, Networking, Web Development, Opinion -->
<datetime class="hidden">2025-12-28T18:00</datetime>

HTTP non si è evoluto. *forzato* cambiare con la fisica, la latenza e l'uso improprio.

Ogni versione esiste perché quella precedente ha colpito un vincolo duro. Se capisci questi vincoli, capisci perché il web funziona come fa - e perché così tante "migliori pratiche" sono in realtà workaround per le limitazioni del protocollo che abbiamo trascinato intorno per trent'anni.

Sto costruendo applicazioni web dal 1997. Ho debuggato HTTP/1.0 tempeste di connessione, guardato browser aprire sei connessioni per host come una "caratteristica," maledetto a HTTP/2 TCP head-of-line blocco su reti mobili, e infine visto HTTP/3 ammettere quello che sapevamo da sempre: la rete è il problema.

Questo non e' un tutorial sul protocollo, e' la storia di come siamo arrivati qui.

[TOC]

## HTTP/1.0: Testo senza stato su tubi non affidabili

### Il mondo che l'ha fatto

HTTP/1.0 è stato progettato nel 1996 per un mondo che non esiste più. Per capire perché ha funzionato, è necessario capire cosa significava "il web" nel 1996:

- **Collegamenti dialup** a 28.8kbps (se siete stati fortunati)
- **Le pagine erano documenti** - testo, magari qualche piccola immagine, collegamenti ipertestuali
- **Gli utenti hanno cliccato e atteso** - risposta istantanea non era previsto
- **I server erano costosi** - università e aziende, non tutti

In questo mondo, il collo di bottiglia era **larghezza di banda**Una pagina da 50KB ci ha messo 15 secondi per scaricare il dialup.

**A cosa serve ottimizzato HTTP/1.0 per:**

- Semplicità (debuggabile con telnet)
- Assenza di Stato (i server non rintracciano le connessioni)
- Leggibilità umana (protocollo testuale)
- Una richiesta, una risposta, connessione chiusa

```
GET /index.html HTTP/1.0
Host: example.com

HTTP/1.0 200 OK
Content-Type: text/html

<html>...
```

Semplice. Elegante. Perfetto per il 1996. E completamente inutilizzabile per qualsiasi cosa oltre il recupero di documenti.

### La pressione che l'ha rotta

Poi la ragnatela e' cambiata.

Nel 1998, le pagine non erano solo documenti. Avevano fogli di stile, JavaScript, immagini multiple. Una singola pagina potrebbe avere bisogno di 20-30 risorse separate.

Ogni singola richiesta richiesta richiesta:

1. **Stretta di mano TCP** (1 RTT)
2. **Richiesta/primo byte** (~1 RTT)
3. **Risposta ricevuta**
4. **Connessione chiusa**
5. Ripeti per ogni immagine, foglio di stile, script...

Una pagina con 20 risorse ha significato 20 strette di mano TCP. Su una connessione di latenza 200ms (ancora comune), che è 4 secondi di *Solo una stretta di mano.* prima di qualsiasi contenuto trasferito.

L'ipotesi fondamentale di HTTP/1.0:

> **Il tempo era scadente.**

Nel 1996, era. La larghezza di banda era il collo di bottiglia. Nel 1999, la larghezza di banda stava migliorando, ma **La latenza non era** - e all'improvviso quei viaggi di andata e ritorno contavano.

HTTP/1.0 è stato progettato per i documenti. Il web era diventato una piattaforma di applicazioni. Qualcosa doveva dare.

## HTTP/1.1: Patch it

### Il mondo che l'ha fatto

HTTP/1.1 è arrivato nel 1997, proprio mentre il web stava esplodendo. Il boom di dotcom stava iniziando. Ogni azienda aveva bisogno di un sito web. Le pagine web stavano diventando complesse - tabelle per il layout, JavaScript per l'interattività, immagini ovunque.

La pressione era chiara: **connessione-per-richiesta stava uccidendo le prestazioni**. Ma completamente riprogettare HTTP non era un'opzione. Troppa infrastruttura già dipendeva da esso. La soluzione doveva essere retro-compatibile.

**Che cosa è cambiato:**

- **Collegamenti persistenti** (`Connection: keep-alive` per impostazione predefinita) - riutilizzare la connessione TCP
- **Codifica di trasferimento cucita** (reazioni di flusso senza conoscere la dimensione in anticipo)
- **Intestazioni host** (hosting virtuale - siti multipli per IP, cruciali per l'hosting condiviso)
- **Caching semantica** (`Cache-Control`, `ETag`, richieste condizionali)
- **Pipelining** (inviare più richieste senza attendere le risposte)

**Che cosa non è cambiato:**

- Risposte sequenziali (anche con pipelining)
- Intestazioni di testo ancora (ripetite su ogni richiesta)
- Ancora una risposta alla volta per connessione

```
GET /page.html HTTP/1.1
Host: example.com
Connection: keep-alive

HTTP/1.1 200 OK
Transfer-Encoding: chunked
Cache-Control: max-age=3600

...
```

### Perché ha funzionato

HTTP/1.1 in realtà non ha risolto il problema delle prestazioni.

**Il Pipelining e' stato un fallimento.** La specifica ha permesso l'invio di richieste multiple su una connessione, ma:

- Responses should to come back *in ordine* (blocco frontale)
- Una risposta lenta bloccava tutto quello che c'era dietro.
- Buggy proxy mangled richieste pipelined
- La maggior parte dei browser disabilitati completamente

Così i browser truffati. Invece di fissare il protocollo, hanno lavorato intorno:

- Apri **6 connessioni parallele per host** (limite del browser)
- Uso **sharding del dominio** (`static1.example.com`, `static2.example.com`) per moltiplicare le connessioni
- **Fogli di sporcizia** per combinare le immagini
- **Bundling CSS/JS** ridurre le richieste
- **CDN** ridurre la latenza

Niente di tutto questo era il protocollo che funzionava come progettato. Era l'intero ecosistema che compensava la limitazione fondamentale di HTTP/1.1.

> **HTTP/1.1 scalata imbrogliando, non fissando il modello.**

### Perché è sopravvissuto comunque

HTTP/1.1 lavorato *abbastanza bene* per quindici anni. Non perché fosse buono, ma perché l'ambiente compensava:

- **Arriva la banda larga.** 20ms strette di mano invece di 200ms. Il dolore era tollerabile.
- **La legge di Moore mi ha aiutato.** I server potrebbero gestire sei connessioni per browser entro il 2005.
- **I CDN hanno mascherato il problema.** Server Edge a 20 metri di distanza invece di 200.
- **Il desktop e' dominato.** Collegamenti cablati, bassa latenza, reti affidabili.

Il protocollo era ancora rotto, siamo stati fortunati che il mondo lo nascondesse.

### Il costo reale

Quei sei collegamenti per ospite non erano gratuiti:

- Ogni connessione significava un'altra stretta di mano TCP
- Ogni connessione competeva per la larghezza di banda
- I server hanno dovuto mantenere più connessioni simultanee
- **Blocco Head-of-line appena spostato su TCP** - perdere un pacchetto su una connessione, quella connessione si blocca

Il web è diventato più veloce nell'era HTTP/1.1. Ma non a causa di HTTP/1.1. È diventato più veloce perché:

- Le reti sono diventate più veloci
- Caching è diventato più intelligente
- CDN assorbito latenza
- I browser hanno migliorato il parallelismo

Stavamo costruendo una piattaforma applicativa su un protocollo di recupero documenti, il protocollo stava perdendo, ma non l'abbiamo ancora sentito.

## La scomoda verità nessuno ammette

Entro il 2010, le prestazioni web sono state una battaglia costante contro l'HTTP stesso.

Le "migliori pratiche" dell'epoca raccontano la storia:

- Concatena tutto il tuo JavaScript in un unico file
- Sprite tutte le vostre immagini insieme
- CSS critico in linea
- Utilizzare gli URI dei dati per evitare richieste
- Domain shard per aprire più connessioni
- Metti gli script in fondo alla pagina

Ognuno di questi è una soluzione per "HTTP/1.1 non può gestire molte richieste in modo efficiente."

Ho costruito molti di questi piccoli strumenti come generatori di sprite, compressori CSS, abbiamo iniziato a usare la compressione di risposta ecc...

I browser non erano più veloci perché HTTP migliorato. Erano più veloci perché essi **lavorato intorno HTTP**.

Sei connessioni per host non è una caratteristica. E 'un hack. Domain sharding non è una buona pratica. E 'un'ammissione di fallimento.

Ho passato anni ad insegnare agli sviluppatori a combinare risorse, immagini sprite e risorse critiche in linea. Niente di tutto questo era "buona architettura." **controllo dei danni al protocollo**.

Il mito "HTTP è semplice" persiste perché la complessità era nascosta in:

- Gestione delle connessioni del browser
- Logica del bordo CDN
- Genera concatenazione strumento
- Messa in comune della connessione al server

HTTP/1.1 ha funzionato perché tutto *intorno* Ha fatto gli straordinari per compensare.

Se hai mai visto un diagramma di HTTP che non mostra modalità di latenza, perdita o guasto, ti sta mentendo. Il protocollo è semplice. La realtà non lo è.

## HTTP/2: abbiamo corretto il livello sbagliato

### Il mondo che l'ha fatto

Nel 2010, il web si era trasformato di nuovo. Due massicci cambi cambiarono tutto:

**1. Mobile è accaduto.**
L'iPhone lanciato nel 2007. Entro 2012, il traffico web mobile stava esplodendo. Improvvisamente gli utenti non erano su banda larga cablata - erano su 3G, poi 4G, con latenza variabile e perdita frequente di pacchetti. Le ipotesi che hanno reso HTTP/1.1 tollerabile stavano rompendo.

**2. Le applicazioni Web hanno sostituito le pagine web.**
Gmail. Google Maps. Facebook. Twitter. Questi non erano documenti con collegamenti. Erano applicazioni che avevano bisogno di decine o centinaia di risorse, aggiornamenti in tempo reale, e risposta immediata. L'hack "sei connessioni per host" stava mostrando la sua età.

Google sentiva questo dolore acutamente. Avevano enormi dimensioni, ingegneri ossessionati dalle prestazioni, e i dati per dimostrare HTTP/1.1 è stato il collo di bottiglia. Nel 2009, hanno iniziato SPDY - un protocollo sperimentale che ha influenzato pesantemente HTTP/2 (non identico, ma la stessa direzione).

**Che cosa è cambiato:**

- **Framing binario** (non testo - analisi più efficiente)
- **Multiplexing** (richieste/risposte multiple interlacciate su una connessione)
- **Compressione intestazione** (HPACK - non ripetere più le stesse intestazioni)
- **Push del server** (inviare le risorse prima che il cliente chiede - anche se questo si è rivelato difficile da sintonizzare correttamente e ora è in gran parte deprecato)
- **Collegamento singolo per origine** (nessuna più esplosione di connessione)

```
┌──────────────────────────────────────────┐
│           Single TCP Connection          │
├──────────────────────────────────────────┤
│ Stream 1: GET /page.html                 │
│ Stream 3: GET /style.css                 │
│ Stream 5: GET /app.js                    │
│ Stream 7: GET /logo.png                  │
│ (all interleaved, no ordering required)  │
└──────────────────────────────────────────┘
```

Questo è ciò che dovrebbe essere il pipelining HTTP/1.1. I flussi sono indipendenti. Una risposta lenta non blocca gli altri. Le intestazioni sono compresse. Il protocollo finalmente corrisponde a come usiamo effettivamente il web.

### Perché ha funzionato (sulle reti giuste)

HTTP/2 è stato **perfetto per il web a banda larga**. E nel 2015, quando ha standardizzato, la banda larga era onnipresente nel mondo sviluppato.

**Cosa è migliorato:**

- Latenza sotto carico leggero (una connessione, nessuna stretta di mano in alto per richiesta)
- Meno connessioni (meno server overhead, meno TCP slow-start)
- Migliore utilizzo della banda (nessun limite di connessione artificiale)
- Compressione dell'intestazione (le intestazioni ripetute come i cookie non costano più la larghezza di banda)
- Non serve più concatenazione/spriting (molti piccoli file vanno bene ora)

Per gli utenti su connessioni cablate con bassa perdita di pacchetti, HTTP/2 è stato un vero e proprio miglioramento. I benchmark sembrava grande. Le metriche migliorate. Google ha dichiarato la vittoria.

### La pressione che l'ha rotta

Ma il mondo era già andato avanti. **Mobile era ora la maggior parte del traffico web.**

E le reti mobili hanno una proprietà fondamentale che la banda larga non: **perdita di pacchetti è comune e imprevedibile**.

Garanzie TCP **Consegna in ordine**. Se il pacchetto 47 viene perso, i pacchetti 48-100 aspettano che venga ritrasmessa 47 - anche se appartengono a flussi HTTP/2 completamente indipendenti.

```
┌──────────────────────────────────────────┐
│              TCP Receive Buffer          │
├──────────────────────────────────────────┤
│ [pkt 45][pkt 46][  ?  ][pkt 48][pkt 49]  │
│                   ↑                       │
│         Waiting for packet 47             │
│                                          │
│ Stream 1 data: BLOCKED                   │
│ Stream 3 data: BLOCKED                   │
│ Stream 5 data: BLOCKED (has pkt 48-49)   │
│ Stream 7 data: BLOCKED                   │
└──────────────────────────────────────────┘
```

HTTP/2 ha risolto il blocco head-of-line al livello dell'applicazione. Poi TCP lo ha reintrodotto al livello del trasporto.

**Un pacchetto perso blocca tutti i flussi.** Su una connessione cablata pulita, la perdita di pacchetti è rara. Su reti mobili, WiFi lossy, o link congestionati? La perdita di pacchetti è costante. E perché HTTP/2 utilizza un *single* connessione (per disegno), un pacchetto perso ora blocca *tutto* invece di una sola delle sei connessioni.

Prestazioni HTTP/2:

- **Cablato, a bassa perdita**: Eccellente
- **Mobile, perdita moderata**: A volte *peggio* rispetto a HTTP/1.1
- **Alta latenza, eventuali perdite**: Catastrofica

L'ironia: HTTP/2 è stato pensato per risolvere il problema del multiplexing del web - proprio come il cellulare ha reso impossibile la perdita da ignorare. Le garanzie di TCP hanno peggiorato sul cellulare rispetto al protocollo che ha sostituito.

### Perché HTTP/2 feltro più veloce (fino a quando non ha fatto)

Le implementazioni iniziali HTTP/2 hanno mostrato reali miglioramenti:

- Meno connessioni significavano un carico iniziale più veloce (la stretta di mano TLS una volta, non sei volte)
- Compressione dell'intestazione ridotta
- Multiplexing ha funzionato grande per i beni sulla stessa origine

Tutti quegli strumenti che ho costruito per 1.1? Il tutto è andato via con HTTP/2, improvvisamente bundling era una cosa negativa. multiplexing di HTTP/2 è stato grande per le risorse sulla stessa origine, ma non ha aiutato con le richieste di origine incrociata. Abbiamo dovuto costruire nuovi strumenti per impacchettare quelli (webpack su questo sito, per esempio!).

Ma la latenza di coda ha raccontato un'altra storia. *mediana* Il P99 e' peggiorato.

Ho visto questo in prima persona: un client abilitato HTTP/2 attraverso il loro CDN e guardato cellulare P99 latenza *aumento* da 40%. I cruscotti hanno mostrato miglioramento sul desktop. I biglietti di supporto provenivano dagli utenti mobili. Abbiamo trascorso una settimana a capire che il "miglioramento" di HTTP/2 stava peggiorando le cose per la maggior parte del loro traffico.

Quando HTTP/2 funziona, funziona splendidamente. Quando un pacchetto cade su una connessione mobile nel momento peggiore, tutto si blocca. E gli utenti notano congela più di quanto notino mediani veloci.

Il problema fondamentale:

> **HTTP/2 ha ipotizzato che il TCP fosse abbastanza buono.**

Per la banda larga, lo era. Per il cellulare, non lo era. E quando HTTP/2 era standardizzato, il cellulare stava già vincendo. Avevamo spinto fino a TCP potrebbe portarci.

## HTTP/3: Bene, ci spostiamo lungo lo stack

### Il mondo che l'ha fatto

Entro il 2015 le prove erano chiare: **TCP era il problema**.

Google era in esecuzione QUIC sperimentalmente dal 2012. Avevano i dati. Su reti mobili, lossy WiFi, e connessioni ad alta latenza, HTTP/2 su TCP stava fallendo in modi che non potevano essere fissati senza cambiare il livello di trasporto.

Ma non si può solo "fix TCP." È implementato in kernel di sistema operativo. È cotto in ogni router, firewall, e middlebox su Internet. Cambiare TCP significa aspettare decenni per l'intera infrastruttura di Internet per l'aggiornamento.

Così Google ha fatto qualcosa di audace: **Hanno costruito un nuovo protocollo di trasporto in cima all'UDP**.

UDP è "dumb" dal design - invia solo pacchetti senza garanzie. Ma questo è esattamente ciò di cui avete bisogno se si vuole implementare *il tuo* affidabilità semantica. QUIC reimplementa le garanzie di TCP (affidabile, consegna ordinata) ma lo fa **per flusso** invece di per ogni connessione.

HTTP/3 (2022) è HTTP su QUIC. È l'ammissione che dovevamo andare sotto HTTP per correggere HTTP.

**Che cosa è cambiato:**

- **QUIC su UDP** (non TCP)
- **Recupero delle perdite a livello di flusso** (un pacchetto perso blocca solo il suo flusso)
- **Configurazione della connessione più veloce** (0-RTT possibile ripresa)
- **Cifratura per impostazione predefinita** (TLS 1.3 integrato in QUIC)
- **Migrazione della connessione** (sopravvive alle modifiche dell'indirizzo IP)

```
┌──────────────────────────────────────────┐
│              QUIC Connection             │
├──────────────────────────────────────────┤
│ Stream 1: [pkt][pkt][pkt] ← flowing      │
│ Stream 3: [pkt][ ? ][pkt] ← waiting      │
│ Stream 5: [pkt][pkt][pkt] ← flowing      │
│ Stream 7: [pkt][pkt]      ← flowing      │
│                                          │
│ Lost packet only affects Stream 3        │
└──────────────────────────────────────────┘
```

**Quello che rimaneva lo stesso:**

- Semantica HTTP (GET, POST, intestazioni, codici di stato)
- Logica di caching
- Modelli REST
- Tutto al livello dell'applicazione

> **HTTP/3 non ha cambiato HTTP. Ha cambiato il modo in cui HTTP sopravvive alla realtà.**

### Perché le questioni QUIC

QUIC implementa le garanzie di affidabilità di TCP *per flusso*Questa e' l'intuizione chiave.

**La promessa di TCP:** "Ogni byte arriva in ordine."
**La promessa di QUIC:** "Ogni byte *in questo flusso* arriva in ordine."

Questa distinzione è il motivo per cui HTTP/3 non collassa sulle reti lossy.

Altre caratteristiche QUIC che fissano problemi di lunga data:

**Migrazione della connessione:**

```
Phone on WiFi → walks out of range → switches to cellular
TCP: Connection dies. Restart everything.
QUIC: Connection ID maintained. Streams continue.
```

Questo è importante perché gli utenti mobili *costantemente* Cambiare rete. Uscire di casa, perdere WiFi, passare al cellulare. Con TCP, ogni connessione muore. Con QUIC, la connessione continua.

**Ripresa 0-RTT:**

```
First connection: Full handshake (1-RTT)
Returning user: Send data immediately (0-RTT)
```

**Cifratura ovunque:**

```
TCP + TLS: Handshake, then encrypted tunnel
QUIC: Encryption is the handshake (TLS 1.3 integrated)
```

### Il mondo che ne ha bisogno

HTTP/3 è progettato per il mondo in cui viviamo:

- **Mobile-first**: Più della metà del traffico web è mobile
- **Reti inaffidabili**: WiFi, cellulare, reti pubbliche congestionate
- **Utenti globali**: Collegamenti ad alta latenza a server distanti
- **Aspettative in materia di privacy**: La cifratura è obbligatoria, non facoltativa

Il protocollo finalmente corrisponde alla realtà della rete. Trent'anni dopo che HTTP/1.0 ha assunto connessioni cablate affidabili, HTTP/3 riconosce che l'affidabilità è l'eccezione, non la regola.

### Il costo del progresso

HTTP/3 non è gratuito:

- **UDP è spesso bloccato** da firewall aziendali (richiesto ritorno a HTTP/2)
- **Più CPU** per l'implementazione dello spazio utente di QUIC (non nel kernel come TCP, anche se questo gap si sta chiudendo con bypass del kernel e stack ottimizzati)
- **Nuovi strumenti di debug** (tcpdump mostra UDP crittografato, HTTP non leggibile)
- **Interferenze tra middlebox** (alcune reti strangolano UDP in modo imprevedibile)

Ma per le applicazioni mobile-first, reti inaffidabili e servizi sensibili alla latenza, HTTP/3 è la prima versione che corrisponde a come le reti si comportano effettivamente.

## La vera lezione in tutte le versioni

Ogni cambiamento di versione HTTP è avvenuto perché **l'ambiente è cambiato più velocemente del protocollo**.

| Versione | Era | Ambiente | Assunzione | Perché si è rotta |
|---------|-----|-------------|------------|--------------|
| HTTP/1.0 | 1996 | Dialup, documenti | Bandwidth is the bottleneck | Pages become apps, latenza materiad |
| HTTP/1.1 | 1999-2015 | banda larga, applicazioni web | bassa latenza nasconde inefficienza | Mobile è arrivato con perdita di pacchetto |
| HTTP/2 | 2015-2022 | Picco a banda larga, rialzo mobile | TCP è abbastanza affidabile | Mobile è diventato dominante, TCP fallito |
| HTTP/3 | 2022+ | Mobile-first, global | Nothing is affidable | Still deploying... |

Il modello è chiaro:

1. Il protocollo è progettato per l'ambiente attuale
2. Cambiamenti ambientali (più velocemente dei protocolli possono adattarsi)
3. Si accumulano soluzioni di lavoro (CDN, hack di connessione, bundling)
4. Il nuovo protocollo riconosce la realtà
5. Ripeti

Il protocollo continua ad essere spinto più vicino alla rete. Ogni astrazione che sembrava sufficiente è stata rimossa quando l'ambiente lo ha richiesto.

**Altre osservazioni:**

- "Senza Stato" e' una bugia che ci diciamo di dormire la notte.
- La maggior parte delle vittorie di prestazioni provenivano da *workaround*, non purezza del protocollo. CDN, caching proxy, pool di connessione, richiesta coalescenza - tutto compensando le limitazioni del protocollo.
- La cosa "semplice" ha continuato a muoversi. HTTP/1.0 era semplice. Poi abbiamo avuto bisogno di connessioni persistenti. Poi multiplexing. Poi nuovo trasporto. Ogni livello di complessità ha risolto problemi reali.
- **Il tempismo e' importante.** HTTP/2 sarebbe stato perfetto se fosse arrivato nel 2005. Entro 2015, mobile aveva già cambiato il gioco. Il protocollo stava risolvendo il problema di ieri.

## Ciò che non è cambiato da 1.0

Ecco la parte scomoda. Nonostante trent'anni di evoluzione del protocollo:

**Le richieste continuano a fallire.**
Partizione di reti. Server crash. I timeout accadono. Il tuo codice ha ancora bisogno di riprovare la logica.

**Le reti mentono ancora.**
200 OK non significa che la risposta sia corretta. La connessione chiusa non significa che la richiesta non sia riuscita. I timeout non significano che il server non abbia elaborato la tua richiesta.

**Le cache servono ancora dati stantii.**
`Cache-Control` è una richiesta, non un comando. I proxy fanno quello che vogliono. La invalidazione CDN è al massimo possibile.

**I clienti provano ancora male.**
Pulsante di clic dell'utente, non succede nulla, fa clic di nuovo. Ora avete due richieste.

**Gli sviluppatori hanno ancora frainteso l'idempotenza.**
GET dovrebbe essere sicuro. PUT dovrebbe essere idempotente. POST è il wild west. La maggior parte delle API sbaglia.

```csharp
// This is still your problem, regardless of HTTP version
public async Task<Result> CreateOrderAsync(Order order)
{
    // What happens if this times out?
    // Did the server receive it?
    // Did it process it?
    // Will the client retry?
    // Will you create duplicate orders?
    
    // HTTP/3 doesn't save you here.
    // Idempotency keys do.
}
```

> **Se non li capisci, HTTP/3 non ti salverà.**

## Che cosa ho effettivamente imparato

Dopo aver creato applicazioni web in tutte queste versioni di protocollo, ecco cosa si è bloccato:

**1. Il protocollo non è il vostro livello di affidabilità.**

HTTP ti dà la semantica richiesta/risposta. Non garantisce la consegna, la correttezza o l'elaborazione esattamente una volta. Questo è il tuo lavoro.

**2. La latenza è il nemico, non la larghezza di banda.**

La maggior parte dei problemi di prestazione sono legati a andata e ritorno, non throughput limitato. La riduzione delle richieste conta più di comprimere payload.

**3. Ogni "best practice" ha una data di scadenza.**

Domain sharding era essenziale per HTTP/1.1. E 'attivamente dannoso per HTTP/2 (rompe il vantaggio di singola connessione). "Bundle everything into one file" è stato gospel; ora la spedizione di molti piccoli moduli su HTTP/2 o HTTP/3 è spesso meglio. La tattica cambia. L'obiettivo (ridurre la latenza) rimane lo stesso.

**4. Misurare sulle reti reali.**

I parametri di riferimento sul localhost non provano nulla. I tuoi utenti sono su reti mobili, hotel WiFi e connessioni in caffetteria saturi.

**5. Le parti noiose contano di più.**

Timeout. Ritiri. Interruttori. Idempotenza. Connection pooling. Questi dettagli poco glamour determinano se il sistema funziona sotto carico.

## Conclusione

HTTP non è diventato più veloce perché è diventato più intelligente. È diventato più veloce perché abbiamo finalmente ammesso **la rete era il problema**.

Ogni versione era giusta per il suo tempo:

- **HTTP/1.0** era perfetto per il recupero dei documenti dialup
- **HTTP/1.1** era perfetto per applicazioni web a banda larga
- **HTTP/2** era perfetto per connessioni cablate a bassa perdita
- **HTTP/3** è costruito per la prima realtà di rete mobile-inaffidabile in cui viviamo

L'errore è stato quello di pensare che qualcuno di loro fosse una soluzione permanente, che rispondesse a pressioni ambientali specifiche; quando l'ambiente cambiava, il protocollo doveva seguire.

**Le versioni HTTP non sono aggiornamenti in senso consumer. Sono compromessi ottimizzati per diverse distribuzioni fallimentari.**

E ancora, dopo tutto questo, i fondamenti rimangono:

- Richieste fallite
- Le reti mentono
- La cache e' dura.
- Questioni relative all'impotenza

Il protocollo si e' evoluto, i problemi non sono scomparsi, si sono solo spostati.

Costruire sistemi che sopravvivano a guasti. Testare su reti reali. Capire che ogni versione HTTP è un tradeoff modellato dalla sua epoca, non un upgrade che obsoleto ciò che è venuto prima.

Sono trent'anni di HTTP. Questo è il web che abbiamo costruito. E in un altro decennio, le ipotesi di HTTP/3 saranno probabilmente datate come quelle di HTTP/1.0.

## Ulteriore lettura

- [RFC 9114: HTTP/3](https://datatracker.ietf.org/doc/html/rfc9114) - Il disciplinare ufficiale
- [RFC 9000: QUIC](https://datatracker.ietf.org/doc/html/rfc9000) - Il protocollo di trasporto
- [Spiegato HTTP/2](https://http2-explained.haxx.se/) - L'eccellente panoramica di Daniel Stenberg
- [Networking del browser ad alte prestazioni](https://hpbn.co/) - Immersione profonda di Ilya Grigorik (libero online)