Guida al Time To First Byte: cos’è e come ottimizzare le pagine
È una metrica che non fa parte dei Core Web Vitals, ma anticipa (e per certi versi sottende e influenza) uno di questi parametri e non solo: insomma, dedicarvi attenzione non è obbligatorio in ottica ranking, ma è sicuramente una prassi consigliata per migliorare in generale le prestazioni del sito e la user experience sulle nostre pagine. Scopriamo tutto ciò che serve sapere su Time To First Byte, un indicatore utile per la reattività del server web e delle risorse di rete coinvolte nel servire il sito, analizzando gli aspetti teorici e anche i più concreti interventi per ottimizzare le nostre pagine.
Che cos’è Time To First Byte o TTFB
Time to First Byte – solitamente indicato con la sigla TTFB – è una metrica fondamentale delle prestazioni web che si riferisce al tempo che intercorre tra la richiesta di una pagina da parte del browser e il momento in cui riceve il primo byte di informazioni dal server.
Questo tempo per il primo byte aiuta quindi a determinare la reattività di un server web, perché misura la quantità di tempo che passa tra la creazione di una connessione al server e l’effettivo download dei contenuti di una pagina web, includendo la ricerca DNS e la creazione della connessione utilizzando un handshake TCP e un handshake SSL, se la richiesta viene effettuata tramite HTTPS.
Cosa misura TTFB e perché è importante per i siti (e la SEO)
TTFB è una metrica che misura il tempo che intercorre tra la richiesta di una risorsa e l’inizio dell’invio del primo byte di una risposta ed è fondamentale per misurare il tempo di configurazione della connessione e la reattività del server Web sia in laboratorio che sul campo.
In concreto, può aiutarci a identificare se il server web è troppo lento per rispondere alle richieste, e – nel caso di richieste di navigazione, ovvero richieste per un documento HTML – precede ogni altra metrica significativa delle prestazioni di caricamento. In particolare, precede due metriche significative per l’esperienza utente come First Contentful Paint (FCP) e soprattutto Largest Contentful Paint (LCP), che sappiamo essere un Core Web Vitals di Google, e quindi valori elevati di TTFB aggiungono tempo alle metriche che lo seguono, influenzando negativamente la qualità dell’esperienza dell’utente e, di conseguenza, anche il giudizio di Google.
Nello specifico, Time to First Byte misura in millesecondi il tempo che intercorre tra l’inizio della richiesta HTTP inviata dal browser dell’utente e il primo byte restituito dal server; quando il browser comincia a ricevere contenuti, può iniziare a costruire la pagina davanti all’utente.
Dal punto di vista tecnico, TTFB è la somma delle seguenti fasi di richiesta, come ci spiega questo utile approfondimento di Jeremy Wagner e Barry Pollard su web.dev:
- Tempo di redirect.
- Tempo di avvio del service worker (se applicabile).
- DNS lookup.
- Connessione e negoziazione TLS.
- Richiesta, fino al punto in cui è arrivato il primo byte della risposta.
Come ulteriore indicazione utile, i Googler anticipano che ridurre la latenza nel tempo di configurazione della connessione e sul back-end contribuisce a ridurre il TTFB.
Quali sono i valori di Time To First Byte e cosa significano
I siti web hanno modi differenti di fornire i contenuti, e quindi le soglie del TTFB sono una “guida approssimativa” e devono essere valutate rispetto al modo in cui il singolo sito specifico serve i suoi contenuti principali.
In linea di massima, Google ritiene consigliabile che il server risponda alle richieste di navigazione abbastanza rapidamente, in modo che il 75° percentile degli utenti riscontri un FCP all’interno della soglia “buona”. Per dare un valore approssimativo di riferimento, la maggior parte dei siti dovrebbe sforzarsi di avere un TTFB di 0,8 secondi o meno.
Un TTFB basso è fondamentale per far arrivare il markup al cliente il prima possibile, ma come dicevamo molto dipende dalle caratteristiche del sito. Ad esempio, dice ancora l’approfondimento, se un sito Web fornisce rapidamente il markup iniziale, ma tale markup richiede JavaScript per popolarlo con contenuti significativi – come nel caso delle Single Page Application (SPA) – raggiungere il TTFB più basso possibile è particolarmente importante in modo che il client-rendering del markup possa avvenire prima.
Al contrario, un sito server-rendered che non richiede tanto lavoro lato client può avere un TTFB leggermente superiore e più basso, a patto di garantire buoni valori FCP e LCP.
Di base, poi, non dobbiamo dimenticare che TTFB non è una metrica Core Web Vitals, quindi non è assolutamente necessario che i siti soddisfino la soglia “buona” del TTFB, a condizione che ciò non impedisca la loro capacità di ottenere buoni punteggi nelle metriche che contano.
Come misurare TTFB
Il Time to First Byte può essere misurato in laboratorio o sul campo.
Gli strumenti sul campo sono Chrome User Experience Report e la library Javascript web-vitals, mentre gli strumenti di laboratorio sono nel pannello di rete di DevTools di Chrome e WebPageTest.
Come chiarisce Wagner in un secondo approfondimento, è importante osservare come questo parametro influisce concretamente sugli utenti del sito web: la fonte primaria per verificare il TTFB in tal senso sono i dati sul campo perché la metrica è influenzata dai redirect, mentre gli strumenti lab-based vengono spesso misurati utilizzando l’URL finale, quindi mancano di questo ulteriore ritardo.
In senso più pratico, come per l’ottimizzazione di ogni metrica, l’approccio consigliato è misurare il TTFB sul campo, utilizzare gli strumenti di laboratorio per approfondire le cause e quindi applicare le ottimizzazioni ove possibile. Dobbiamo quindi tenere d’occhio i dati sul campo e apportare le modifiche necessarie per garantire che l’esperienza utente sia più rapida possibile.
In JavaScript, possiamo misurare il TTFB delle richieste di navigazione nel browser con l’API Navigation Timing. Nell’esempio in immagine, vediamo come creare un’istanza PerformanceObserver che ascolta una voce navigation e la registra nella console:
Tuttavia, non tutti i browser supportano PerformanceObserver o il suo flag buffered: per ottenere il massimo supporto browser possibile, dovremmo prendere in considerazione l’adozione del pacchetto web-vitals.
Sempre in ambito JS, infatti, la library web-vitals può misurare il TTFB nel browser con minore complessità, come mostrato qui sotto:
C’è però un altro aspetto da valutare: il TTFB si applica a tutte le richieste, non solo alle richieste di navigazione, e in particolare le risorse ospitate su server multiorigine possono introdurre latenza a causa della necessità di impostare connessioni a tali server.
Potrebbe quindi essere più opportuno misurare il TTFB con le risorse sul campo, utilizzando l’API Resource Timing all’interno di un PerformanceObserver: questo snippet di codice è simile a quello utilizzato per misurare il TTFB per una richiesta di navigazione, tranne che invece di interrogare le voci “navigation'”, interroga le voci “resource”. Inoltre, tiene anche conto del fatto che alcune risorse caricate dall’origine primaria possono restituire un valore di 0, poiché la connessione è già aperta o una risorsa viene recuperata istantaneamente da una cache.
Anche in questo caso c’è un però molto importante: il TTFB per le richieste cross-origin non sarà misurabile nel campo se i server cross-origin non riescono a impostare un’intestazione Timing-Allow-Origin.
Come capire se il Time to First Byte è alto
Possiamo usare il response header Server-Timing nel back-end della nostra applicazione per misurare processi back-end distinti che potrebbero contribuire a un’elevata latenza. La struttura del valore dell’intestazione è flessibile e accetta, come minimo, un handle da noi definito: i valori facoltativi includono un valore di durata (tramite dur), nonché una descrizione facoltativa leggibile dall’utente (tramite desc).
Serving-Timing può servire a misurare molti processi di back-end dell’applicazione, ma ce ne sono alcuni a prestare particolare attenzione:
- Interrogazioni al database.
- Tempo di rendering lato server, se applicabile.
- Disk seek.
- Hit/Miss nell’edge server cache (se usiamo un CDN).
Tutte le parti di una voce Server-Timing sono separate da due punti, e più voci possono essere separate da una virgola. L’header può essere impostato utilizzando la lingua scelta dal back-end dell’applicazione, e il seguente è un esempio fatto in PHP:
Impostando questa intestazione emergono informazioni che possiamo utilizzare sia in laboratorio che sul campo.
Sul campo, qualsiasi pagina con una response header Server-Timing impostata popolerà la proprietà Server-Timing nell’API Navigation Timing:
In laboratorio, i dati del response header Server-Timing verranno visualizzati nel riquadro dei tempi della scheda Rete in Chrome DevTools:
In questa immagine, i valori dell’intestazione Server-Timing misurano se un edge server del CDN ha rilevato o meno un hit o miss della cache, nonché il tempo necessario per recuperare la risorsa dall’edge e dal server di origine. In pratica, quindi, in questo caso Server-Timing serve a misurare se una richiesta per una risorsa ha raggiunto la cache CDN e quanto tempo impiega la richiesta per raggiungere l’edge server della CDN e quindi l’origine.
Se la misurazione della latenza di back-end Server-Timing non è fattibile, allora un’alternativa adatta potrebbe essere quella di fare affidamento su Application Performance Monitoring (APM) per rilevare e diagnosticare problemi di prestazioni di back-end.
Come ottimizzare Time To First Byte e servire più rapidamente i contenuti
Dopo aver determinato la presenza di un TTFB problematico analizzando i dati disponibili, possiamo passare alla risoluzione del problema e all’ottimizzazione del parametro.
Secondo Wagner, l’aspetto più impegnativo dell’ottimizzazione del Time To First Byte è che, mentre lo stack di frontend del Web sarà sempre HTML, CSS e JavaScript, gli stack di backend possono variare in modo significativo. Esistono numerosi stack di back-end, loro combinazioni e prodotti di database, ognuno con le proprie tecniche di ottimizzazione, e quindi non è possibile racchiudere in un articolo tutto ciò che possiamo fare per abbassare il TTFB del nostro sito web.
I seguenti consigli, quindi, rappresentano alcune opzioni che possiamo esplorare per provare a far funzionare le cose un po’ più velocemente sul lato server e si applicano alla maggior parte delle architetture.
La piattaforma usata per ospitare il sito web può avere un forte impatto sul TTFB: ad esempio, le prestazioni di WordPress sono influenzate dal numero e dalla qualità dei plugin o dai temi utilizzati, e così anche altre piattaforme sono influenzate dal livello di personalizzazione applicata personalizzata.
Controllare l’hosting
Prima ancora di prendere in considerazione altri approcci di ottimizzazione, l’hosting dovrebbe essere la prima cosa da considerare, dice la guida degli sviluppatori del team di Chrome DevRel, rispettando una regola generale piuttosto intuitiva: l’host del sito web deve essere in grado di gestire il traffico che inviamo.
L’hosting condiviso sarà generalmente più lento, ma ciò potrebbe non essere un problema per chi gestisce un piccolo sito Web personale che serve principalmente file statici (che comunque può applicare alcune di queste tecniche di ottimizzazione per ridurre il TTFB); al contrario, se gestiamo un’applicazione più grande con molti utenti che prevede la personalizzazione, querying del database e altre operazioni intensive sul lato server, la scelta dell’hosting diventa fondamentale per ridurre il Time To First Byte sul campo.
Nella scelta di un hosting provider dobbiamo prestare attenzione ad alcuni aspetti:
- Quantità di memoria allocata all’istanza dell’applicazione. Se l’applicazione non ha memoria sufficiente, si bloccherà e farà fatica a servire le pagine il più velocemente possibile.
- L’hosting provider mantiene aggiornato il nostro stack di back-end? Man mano che vengono rilasciate nuove versioni dei linguaggi di back-end dell’applicazione, delle implementazioni HTTP e del software di database, le prestazioni di quel software miglioreranno nel tempo, ed è quindi fondamentale rivolgersi a hosting provider che dia la priorità a questo tipo di manutenzione cruciale.
- Se abbiamo requisiti applicativi molto specifici e desideriamo l’accesso di livello più basso ai file di configurazione del server, possiamo valutare la possibilità di personalizzare il back-end della nostra istanza dell’applicazione.
Per valutare le prestazioni TTFB dell’utente reale di ogni hosting provider e verificare quelle dei concorrenti possiamo visitare la pagina ismyhostfastyet.com (gestita da un altro Googler, Rick Viscomi), che riporta appunto tutte le informazioni utili.
Utilizzare un CDN
Il consiglio a rivolgersi a un Content Delivery Network torna spesso nei discorsi legati all’ottimizzazione delle prestazioni del sito e nella SEO tecnica, ed è per una buona ragione, dice Wagner: anche se abbiamo un back-end dell’applicazione molto ben ottimizzato, gli utenti che si trovano lontano dal server di origine potrebbero comunque riscontrare un TTFB elevato sul campo.
I CDN risolvono il problema della vicinanza dell’utente dal server di origine utilizzando una rete distribuita di server – chiamati edge server – che memorizza nella cache le risorse su sistemi che sono fisicamente più vicini agli utenti che ne fanno richiesta.
Oltre ai server edge, i fornitori di CDN possono anche offrire altri vantaggi quali:
- I provider CDN di solito offrono tempi di risoluzione DNS estremamente rapidi.
- Un CDN probabilmente servirà i contenuti dai server edge utilizzando protocolli moderni come HTTP/2 o HTTP/3.
- HTTP/3 in particolare risolve il problema di blocco dell’head-of-line presente in TCP (su cui si basa HTTP/2) utilizzando il protocollo UDP.
- Un CDN probabilmente fornirà anche versioni moderne di TLS, riducendo così la latenza coinvolta nel tempo di negoziazione TLS – TLS 1.3 in particolare è progettato per mantenere la negoziazione TLS il più breve possibile.
- Alcuni provider CDN forniscono una funzionalità spesso chiamata “edge worker“, che utilizza un’API simile a quella dell’API Service Worker per intercettare le richieste, gestire a livello di codice le risposte nelle cache edge o riscrivere del tutto le risposte.
- I provider CDN sono molto bravi a ottimizzare la compressione – che è difficile da ottenere da soli e può portare a tempi di risposta più lenti in alcuni casi con markup generato dinamicamente, che deve essere compresso al volo.
- I provider CDN inoltre memorizzeranno automaticamente nella cache le risposte compresse per le risorse statiche, portando alla migliore combinazione di rapporto di compressione e tempo di risposta.
Sebbene l’adozione di un CDN comporti una quantità variabile di sforzi, da banali a significativi, dovrebbe essere un’alta priorità da perseguire nell’ottimizzazione del TTFB.
Evitare i redirect di più pagine
Un potenziale fattore che contribuisce a un TTFB elevato sono i redirect, che si verificano quando una richiesta di navigazione per un documento riceve in risposta dal browser l’informazione che la risorsa esiste in un’altra posizione. Un solo reindirizzamento può certamente aggiungere latenza indesiderata a una richiesta di navigazione, ma la cosa può ulteriormente peggiorare se quel redirect punta a un’altra risorsa che si traduce in un altro reindirizzamento e così via – la famosa catena di redirect.
Esistono due tipi di reindirizzamenti, sintetizza Wagner:
- Reindirizzamenti della stessa origine (same-origin redirects), in cui il reindirizzamento avviene interamente sullo stesso sito web.
- Reindirizzamenti di origine incrociata (cross-origin redirects), in cui il reindirizzamento si verifica inizialmente su un’altra origine – ad esempio da un servizio di abbreviazione dell’URL di un social media – prima di arrivare al sito web.
Chiaramente, dobbiamo concentrarci sull’eliminazione dei reindirizzamenti same-origin, perché è su questi che abbiamo il controllo diretto, andando a controllare i link interni sul nostro sito Web per vedere se qualcuno di essi risulta fornire in un codice di risposta 302 o 301.
I reindirizzamenti cross-origin sono più complicati, in quanto spesso sono al di fuori del nostro controllo, ma possiamo come regola di bare evitare redirect multipli quando possibile, ad esempio utilizzando più link shorteners durante la condivisione dei link.
Un’altra importante fonte di tempo di reindirizzamento può provenire dai redirect da HTTP a HTTPS. Un modo per aggirare questo problema è utilizzare l’header Strict-Transport-Security (HSTS), che imporrà HTTPS alla prima visita a un’origine, quindi dirà al browser di accedere immediatamente all’origine tramite lo schema HTTPS nelle visite future. Una volta adottata una buona politica HSTS, possiamo velocizzare le cose alla prima visita a un’origine aggiungendo il sito all’elenco di precaricamento HSTS (ma l’articolo avverte anche di essere cauti nell’implementazione di HSTS, poiché l’impostazione di una policy troppo aggressiva senza test sufficienti può danneggiare il sito web).
Gestire la trasmissione del markup al browser
I browser sono ottimizzati per elaborare il markup in modo efficiente quando viene trasmesso in streaming, il che significa che il markup viene gestito in blocchi man mano che arriva dal server. Questo è fondamentale per quanto riguarda i payload di markup di grandi dimensioni, poiché permette al browser di analizzare i blocchi di markup in modo incrementale, anziché attendere l’arrivo dell’intera risposta prima che possa iniziare l’analisi.
Anche se i browser sono bravi a gestire la trasmissione di markup, è fondamentale fare tutto il possibile per mantenere lo streaming fluente in modo che quei bit iniziali di markup siano in arrivo il prima possibile, ed è un problema se il back-end sta bloccando le cose.
In ambito JavaScript, ad esempio, React e altri framework che possono eseguire il rendering del markup su richiesta sul server hanno utilizzato un approccio sincrono al rendering lato server; tuttavia, le versioni più recenti di React hanno implementato metodi server per lo streaming del markup direttamente durante il rendering, e ciò implica che non serve attendere che un metodo API del server React esegua il rendering dell’intera risposta prima che sia inviata.
Non tutti i runtime JavaScript possono sfruttare il rendering lato server in streaming, però: i più recenti come Deno lo supportano immediatamente, ma le versioni precedenti di Node.js potrebbero non supportarlo.
Un altro modo per garantire che il markup venga trasmesso rapidamente al browser è affidarsi al rendering statico, che genera file HTML durante il tempo di compilazione. Con il file completo immediatamente disponibile, i server Web possono iniziare a inviare immediatamente il file e la natura ereditaria di HTTP si tradurrà in un markup di streaming. Sebbene questo approccio non sia adatto a tutte le pagine di tutti i siti Web, ad esempio quelli che richiedono una risposta dinamica come parte dell’esperienza dell’utente, può essere vantaggioso per quelle pagine che non richiedono la personalizzazione del markup per un utente specifico.
Utilizzare un service worker
L’API Service Worker può avere un grande impatto sul TTFB sia per i documenti che per le risorse che caricano, perché un service worker funge da proxy tra il browser e il server, ma l’eventuale impatto sul TTFB del sito Web dipende da come impostiamo il service worker stesso e da quanto questa configurazione è in linea con i requisiti dell’applicazione.
- Utilizzare una strategia stale-while-revalidate per le risorse. Se un asset si trova nella cache del service worker, che si tratti di un documento o di una risorsa richiesta dal documento, la strategia di non validità durante la riconvalida servirà primaquella risorsa dalla cache, quindi scaricherà quell’asset in background e lo servirà dal cache per interazioni future.
- Se abbiamo risorse di documenti che non cambiano molto spesso, l’utilizzo di una strategia stale-while-revalidate può rendere il TTFB di una pagina quasi istantaneo. Tuttavia, questo non funziona così bene se il sito web invia markup generato dinamicamente, come il markup che cambia in base al fatto che un utente sia autenticato: in questi casi, è sempre meglio raggiungere primala rete, in modo che il documento sia il più aggiornato possibile.
- Se il documento carica risorse non critiche che cambiano con una certa frequenza, ma il recupero della risorsa obsoleta non influirà notevolmente sull’esperienza dell’utente, ad esempio immagini selezionate o altre risorse che non sono critiche, il TTFB per tali risorse può essere notevolmente ridotto utilizzando una strategia stale-while-revalidate.
- Utilizzare un’architettura streaming service worker, se possibile. Questa architettura di service worker utilizza un approccio in cui parti di una risorsa documento vengono archiviate nella cache di service worker e combinate con content partial durante la richiesta di navigazione. L’effetto risultante dall’utilizzo di questo modello di service worker è che la navigazione sarà piuttosto veloce, mentre i payload HTML più piccoli vengono scaricati dalla rete. Sebbene questo modello di service worker non funzioni per tutti i siti Web, i tempi TTFB per le risorse dei documenti possono essere praticamente istantanei per i siti che possono utilizzarlo.
- Usare il modello app shell per le applicazioni client-rendered. Questo modello si adatta meglio alle SPA in cui la “shell” della pagina può essere consegnata istantaneamente dalla cache del service worker e il contenuto dinamico della pagina viene popolato e reso successivamente nel ciclo di vita della pagina.
Utilizzare 103 Early Hints per risorse critiche per il rendering
Non importa quanto bene sia ottimizzato il back-end dell’applicazione, potrebbe esserci comunque una quantità significativa di lavoro che il server deve svolgere per preparare una risposta, incluso il lavoro costoso (ma necessario) del database che ritarda l’arrivo della risposta di navigazione il più rapidamente possibile. L’effetto potenziale di ciò è che alcune successive risorse critiche per il rendering potrebbero essere ritardate, come CSS o, in alcuni casi, JavaScript che esegue il rendering del markup sul client.
L’header 103 Early Hints è un primo codice di risposta che il server può inviare al browser mentre il back-end è impegnato a preparare il markup, e può essere utilizzato per suggerire al browser che ci sono risorse critiche per il rendering che la pagina dovrebbe iniziare a scaricare durante la preparazione del markup. Sui browser supportati l’effetto può essere un rendering più rapido dei documenti (CSS) e una disponibilità più rapida delle funzionalità della pagina principale (JavaScript).
Se però il nostro sito non esegue molte elaborazioni sul back-end per preparare il markup, come avviene ai siti statici, 103 Early Hints probabilmente non sarà di grande aiuto, perché tende a funzionare meglio per i siti che richiedono un tempo di back-end considerevole prima che il markup possa essere inviato all’utente.