Early Hints (HTTP 103): Riduci il TTFB con Preload Anticipati nel 2026

Guida pratica a HTTP 103 Early Hints per ridurre il TTFB percepito: configurazione su Cloudflare, Vercel, Nginx e Node.js con esempi di codice e misurazione dell'impatto reale su LCP nel 2026.

Quando il browser invia una richiesta HTTP, attende in silenzio mentre il server costruisce la risposta. In quel lasso di tempo — che a volte è 50 ms, a volte oltre 800 ms — la connessione resta lì, inattiva. Early Hints (HTTP 103) riempie quella pausa permettendo al server di anticipare suggerimenti come preload e preconnect ancora prima che la risposta finale sia pronta. Risultato concreto: LCP più rapido del 10–30% su pagine con backend lenti, secondo i dati pubblicati da Cloudflare e Shopify nel 2025.

Onestamente, è una di quelle ottimizzazioni che mi piacciono parecchio: zero refactoring lato applicazione, zero impatto sui browser non compatibili, e un guadagno misurabile sul campo. In questa guida vediamo come funziona davvero, come implementarlo (Cloudflare, Fastly, Nginx, Express.js, Vercel) e gli errori che possono peggiorare le prestazioni invece di migliorarle.

Cos'è HTTP 103 Early Hints

Early Hints è una risposta HTTP informativa con codice di stato 103, definita nella RFC 8297. Il server può inviarla prima della risposta finale (200 OK, 404 Not Found, ecc.) per dichiarare al client risorse che dovrebbero essere precaricate.

Il flusso è semplice ma potente:

  1. Il browser richiede /articolo
  2. Il server processa la richiesta (query al database, rendering, ecc.)
  3. Mentre il server lavora, invia una risposta 103 Early Hints con Link: </hero.avif>; rel=preload; as=image
  4. Il browser inizia a scaricare hero.avif in parallelo
  5. Quando il server finisce, invia la risposta 200 OK finale con l'HTML

Il guadagno è il tempo di "server thinking" — quei 200–500 ms in cui storicamente il browser non aveva nulla da fare. Tempo morto recuperato.

Differenza tra Early Hints e Resource Hints classici

Molti sviluppatori confondono Early Hints con <link rel="preload"> nell'<head>. La differenza è cruciale, però:

  • Preload nell'HTML: il browser scopre la risorsa solo dopo aver ricevuto il primo byte dell'HTML. Funziona, ma arriva tardi.
  • Early Hints: il browser scopre la risorsa durante il TTFB. Sfrutta tempo morto.

Se il TTFB è di 400 ms e il preload del font CSS richiede 200 ms, con il metodo classico si pagano 600 ms; con Early Hints il font è pronto contestualmente alla risposta finale. Un upgrade gratuito, in pratica.

Supporto browser e server nel 2026

Browser

  • Chrome 103+: supporto stabile dal giugno 2022, attivato di default per la navigazione di alto livello
  • Edge 103+: stesso engine di Chromium
  • Opera 89+: supportato
  • Safari: supporto introdotto in Safari 17.2 (dicembre 2023), limitato a HTTP/2 e HTTP/3
  • Firefox: ancora sotto flag network.early-hints.enabled nel 2026, non supportato di default

I browser che non supportano Early Hints semplicemente ignorano il 103 e procedono normalmente. Niente regressioni, niente fallback da gestire.

Server e CDN

  • Cloudflare: supporto nativo dal 2022, attivabile con un click dalla dashboard o tramite header Link
  • Fastly: supportato via VCL e Compute@Edge
  • Akamai: supportato via Property Manager
  • Vercel: supporto via writeEarlyHints() nelle Edge Functions
  • Nginx: non nativo, richiede modulo ngx_http_early_hints_module o reverse proxy
  • Apache: supportato dalla versione 2.4.55+
  • Node.js: response.writeEarlyHints() dalla versione 18.11+

Implementazione pratica con Node.js ed Express

Il modo più diretto per sperimentare Early Hints è con Node.js 18+. L'API è disponibile direttamente sull'oggetto response:

const express = require('express');
const app = express();

app.get('/articolo/:slug', async (req, res) => {
  // Invia early hints PRIMA di iniziare il lavoro pesante
  res.writeEarlyHints({
    link: [
      '</css/critical.css>; rel=preload; as=style',
      '</fonts/inter-var.woff2>; rel=preload; as=font; type=font/woff2; crossorigin',
      '<https://cdn.example.com>; rel=preconnect',
    ],
  });

  // Ora fai il lavoro lento (DB, rendering, ecc.)
  const articolo = await db.getArticolo(req.params.slug);
  const html = renderTemplate(articolo);

  res.status(200).send(html);
});

app.listen(3000);

Il browser riceve i suggerimenti immediatamente e inizia il download di CSS, font e la connessione TCP/TLS al CDN mentre il database risponde. Magia? No, solo HTTP usato bene.

Quando NON inviare Early Hints

L'API writeEarlyHints() va chiamata solo se sai che la risposta finale userà davvero quelle risorse. Se invii hint per /hero.avif ma poi rendi una pagina d'errore senza quell'immagine, hai sprecato banda dell'utente (e i tuoi soldi di CDN, già che ci siamo).

app.get('/dashboard', async (req, res) => {
  // MALE: invii hint prima di sapere se l'utente è autenticato
  res.writeEarlyHints({
    link: ['</dashboard.css>; rel=preload; as=style'],
  });

  if (!req.user) return res.redirect('/login');
  // ... resto della logica
});

Meglio inviare Early Hints solo dopo i controlli rapidi che non producono effetti collaterali significativi:

app.get('/dashboard', async (req, res) => {
  if (!req.user) return res.redirect('/login');

  // BENE: ora sai che servirà la dashboard
  res.writeEarlyHints({
    link: ['</dashboard.css>; rel=preload; as=style'],
  });

  const data = await fetchDashboardData(req.user.id);
  res.render('dashboard', data);
});

Configurazione su Cloudflare

Cloudflare offre due modalità per Early Hints. La prima è automatica: nella dashboard, in Speed → Optimization → Content Optimization, abilita "Early Hints". Cloudflare cercherà i tag <link rel="preload"> e <link rel="preconnect"> nelle pagine HTML cached e li invierà come 103 alle richieste successive. Letteralmente un toggle.

La seconda modalità è manuale, via header Link dal tuo origin. Cloudflare li trasforma in 103 Early Hints automaticamente:

app.get('/', (req, res) => {
  res.setHeader('Link', [
    '</css/main.css>; rel=preload; as=style',
    '</js/app.js>; rel=preload; as=script',
  ].join(', '));
  res.send(html);
});

Cloudflare invierà 103 Early Hints al browser sulla connessione client-edge anche se la connessione edge-origin non supporta nativamente 103. È il punto di forza dell'avere una CDN davanti.

Configurazione su Vercel ed Edge Functions

Vercel ha aggiunto il supporto a Early Hints nel 2024 per Edge Functions ed Edge Middleware:

// app/articolo/[slug]/route.ts
export async function GET(request: Request) {
  const headers = new Headers();
  headers.append('Link', '</_next/static/css/app.css>; rel=preload; as=style');
  headers.append('Link', '<https://images.cdn.com>; rel=preconnect');

  // Vercel converte automaticamente questi header Link in 103 Early Hints
  // sulla connessione tra edge e browser
  const data = await fetchSlowData();

  return new Response(renderHTML(data), {
    headers: {
      ...Object.fromEntries(headers),
      'Content-Type': 'text/html',
    },
  });
}

Configurazione su Nginx

Nginx non supporta Early Hints di default. Le opzioni sono tre:

  1. Compilare il modulo ngx_http_early_hints_module di terze parti
  2. Usare Nginx come reverse proxy davanti a un backend Node.js che invia 103
  3. Mettere Cloudflare o Fastly davanti a Nginx (l'opzione più pratica, lo dico per esperienza)

Esempio di configurazione Nginx come reverse proxy con il modulo:

server {
    listen 443 ssl http2;
    server_name esempio.it;

    location / {
        proxy_pass http://backend;
        proxy_http_version 1.1;

        # Permetti l'inoltro di risposte 103 Early Hints
        proxy_pass_request_headers on;
        proxy_buffering off;

        # Header che il backend imposterà
        proxy_set_header X-Forward-Early-Hints "true";
    }
}

Quali risorse vale la pena precaricare

Non tutto deve finire in Early Hints. Ecco una scala di priorità basata sul valore reale (non sulla teoria).

1. Risorse che bloccano il rendering (massima priorità)

  • CSS critico nell'<head>: bloccante per il primo paint
  • Web font usati above-the-fold: prevengono il FOUT/FOIT
  • JavaScript critico con defer: eseguito prima dell'interattività

2. Risorse LCP (alta priorità)

  • Immagine hero (con fetchpriority=high)
  • Video poster per LCP video

3. Connessioni anticipate (priorità media)

  • preconnect a CDN immagini, API esterne, Google Fonts
  • dns-prefetch per origin secondari (analytics, ads)

Cosa NON includere

  • Immagini below-the-fold
  • JavaScript di analytics o tag manager
  • Risorse condizionali che potrebbero non servire
  • Bundle CSS completi di centinaia di KB

Una regola empirica che applico ai miei progetti: se la risorsa non è nel critical rendering path, lasciala fuori da Early Hints. Saturare la connessione iniziale con preload non critici peggiora l'LCP, perché compete con l'HTML stesso. Più non è meglio. È peggio.

Misurare l'impatto reale

Per capire se Early Hints sta aiutando il tuo sito hai bisogno di metriche prima/dopo. Senza numeri si naviga a vista. I metodi più affidabili nel 2026:

Chrome DevTools

Apri la tab Network, attiva "Disable cache" e ricarica. Le risposte 103 appaiono come righe separate prima della risposta principale. Nel pannello Timing vedrai Early Hints received con il timestamp esatto.

WebPageTest

WebPageTest mostra Early Hints nel waterfall come una riga blu chiaro distinta dalla risposta finale. Confronta lo Start Render e l'LCP tra due test (uno con Early Hints, uno senza) per quantificare il guadagno.

Real User Monitoring

Con la PerformanceNavigationTiming API puoi misurare l'impatto sul campo, sui tuoi utenti veri:

const nav = performance.getEntriesByType('navigation')[0];
const earlyHintsReceived = nav.firstInterimResponseStart > 0;
const ttfb = nav.responseStart - nav.requestStart;
const earlyHintsLeadTime = nav.responseStart - nav.firstInterimResponseStart;

console.log({ earlyHintsReceived, ttfb, earlyHintsLeadTime });

// Invia a RUM
beacon('/rum', {
  earlyHintsReceived,
  ttfb,
  leadTime: earlyHintsLeadTime,
  lcp: getLCP(),
});

Confronta poi la distribuzione di LCP nei due gruppi (con/senza 103) per vedere il guadagno reale. È il dato che conta — i sintetici mentono spesso.

Errori comuni e come evitarli

Errore 1: Early Hints senza HTTP/2 o HTTP/3

HTTP/1.1 non supporta multiple risposte sulla stessa connessione. Se il tuo server gira ancora su HTTP/1.1, Early Hints non funzionerà — punto. Verifica con curl -I --http2 https://tuosito.it che il protocollo sia HTTP/2 o HTTP/3.

Errore 2: Inviare hint per risorse cached

Se la risorsa è già nella cache HTTP del browser, il preload è uno spreco. Per pagine visitate frequentemente dallo stesso utente, Early Hints offre meno valore. Concentralo sulle prime visite e sulle pagine d'ingresso (homepage, landing page, link da social).

Errore 3: Race condition con il Service Worker

Se hai un Service Worker che intercetta le richieste, le risorse precaricate via Early Hints potrebbero non essere quelle che il SW userà. Controlla il fetch handler del Service Worker e assicurati che le richieste preload siano gestite coerentemente. È un bug subdolo: niente errori in console, ma niente speedup nemmeno.

Errore 4: Inviare troppi hint

Più di 6–8 risorse in Early Hints saturano il bandwidth iniziale e ritardano l'HTML. Tieni la lista corta e prioritaria. Ricorda che il browser ha solo ~14 KB di TCP slow-start nella prima RTT — un budget piccolissimo.

Early Hints vs HTTP/2 Server Push

HTTP/2 Server Push prometteva qualcosa di simile ma è stato deprecato e rimosso da Chrome 106 nel 2022. Il problema era duplice: il server pushava risorse già in cache (spreco), e l'API era complessa da gestire correttamente. Insomma, una buona idea con un'esecuzione difficile.

Early Hints risolve entrambi i problemi:

  • Il browser decide se scaricare la risorsa (rispetta la cache)
  • L'API è solo header HTTP, riusa lo stack esistente

Se nel tuo codebase c'è ancora Server Push, è ora di migrare. Tipo, tre anni fa.

Combinare Early Hints con altre tecniche

Early Hints da solo migliora il TTFB percepito; in combinazione con altre tecniche moltiplica i benefici:

  • + Speculation Rules API: prerendering della pagina successiva + Early Hints sulla nuova pagina = navigazione istantanea
  • + Compression Dictionaries: precarichi CSS/JS più piccoli, compressi al 97% in più
  • + HTTP/3: 0-RTT connection resumption + Early Hints elimina quasi tutta la latenza di connessione
  • + fetchpriority=high sull'immagine LCP: il preload nell'Early Hint diventa ancora più aggressivo

Domande frequenti

Early Hints peggiora le performance se Firefox non lo supporta?

No. Firefox e altri browser non supportati ignorano semplicemente la risposta 103 e procedono come se non esistesse. Non c'è penalità di rete, perché la 103 è una risposta minimale (poche centinaia di byte).

Posso usare Early Hints per pagine HTML statiche servite da un CDN?

Sì, ma il valore è ridotto: le pagine statiche hanno già un TTFB molto basso (sotto 50 ms). Early Hints brilla quando il backend ha latenza significativa (200+ ms) per query DB, rendering server-side o computazioni. Su pagine statiche resta comunque utile per preconnect a domini esterni.

Quanti link posso mettere nell'header Link di una risposta 103?

Tecnicamente il limite è quello dell'header HTTP del server (di solito 8–16 KB). In pratica, tieni la lista sotto le 8 risorse per non saturare il TCP slow-start. Se hai bisogno di precaricare di più, è sintomo di un problema di prioritizzazione — non una carenza di Early Hints.

Early Hints funziona con HTTP/3 e QUIC?

Sì, perfettamente. HTTP/3 mantiene la stessa semantica di HTTP/2 per le risposte intermedie. Anzi, con 0-RTT connection resumption di QUIC, il guadagno è ancora maggiore perché l'handshake TLS è quasi gratuito.

Cosa succede se invio Early Hints e poi la risposta finale è un 301 redirect?

Il browser ignora i preload se la risposta finale è una redirezione e segue il redirect. Le risorse precaricate vengono buttate. Per questo è importante fare i controlli di routing/auth prima di chiamare writeEarlyHints(), come negli esempi sopra.

Conclusione

Early Hints è una delle ottimizzazioni con il miglior rapporto sforzo/risultato disponibili nel 2026. Su Cloudflare richiede un click. Su Node.js è una singola chiamata API. E lo speedup di 100–400 ms sull'LCP per pagine con backend lento è documentato in case study reali (Shopify, Cloudflare, Akamai).

Il mio consiglio? Inizia con un test su una singola pagina chiave (homepage o landing più trafficata), misura prima/dopo con WebPageTest, poi rolla la configurazione progressivamente. È una vittoria silenziosa ma misurabile — e di queste, nel 2026, ne abbiamo bisogno tutti.

Sull'Autore Editorial Team

Our team of expert writers and editors.