TTFB Request Duration: Ridurre il Tempo di Elaborazione del Server

La request duration è il tempo che il tuo server impiega per elaborare una richiesta. È il maggiore contributore al TTFB nella maggior parte dei siti. Scopri Server-Timing, caching, ottimizzazione del database e soluzioni specifiche per piattaforma.

Arjen Karel Core Web Vitals Consultant
Arjen Karel - linkedin
Last update: 2026-03-03

Ridurre la Sotto-parte Request Duration del Time to First Byte

Questo articolo fa parte della nostra guida sul Time to First Byte (TTFB). La request duration è la quinta e ultima sotto-parte del TTFB. Misura il tempo che il tuo server impiega effettivamente per elaborare una richiesta: riceverla, eseguire la logica applicativa, interrogare i database e generare la risposta HTML. Di tutte le sotto-parti del TTFB, la request duration è quella su cui hai il maggior controllo. Nella mia esperienza di audit dei siti con CoreDash, è il singolo maggiore contributore al TTFB lento nella maggior parte dei siti web.

Il Time to First Byte (TTFB) può essere suddiviso nelle seguenti sotto-parti:

Vuoi ottimizzare il Time to First Byte? Questo articolo si concentra sulla parte request duration del Time to First Byte. Se non sei sicuro di cosa significhi request duration, inizia con cos'è il Time to First Byte e identificare e risolvere i problemi di TTFB prima.

Cosa Succede Durante la Request Duration

La request duration inizia nel momento in cui il server riceve la richiesta HTTP e termina quando invia il primo byte della risposta. Tutto ciò che il tuo server fa nel frattempo conta come request duration. Su un tipico sito web dinamico, questo include:

  1. Routing della richiesta: il web server (Nginx, Apache, IIS) riceve la richiesta e la instrada verso il livello applicativo.
  2. Bootstrap dell'applicazione: il framework si inizializza. In WordPress questo significa caricare il core, i plugin attivi e il tema. In Node.js/Express questo significa l'esecuzione dei middleware.
  3. Logica di business: il codice della tua applicazione viene eseguito: controlli di autenticazione, validazione dei permessi, trasformazione dei dati, selezione del template.
  4. Query al database: l'applicazione interroga MySQL, PostgreSQL, MongoDB o qualsiasi data store utilizzato. Questo è spesso il passaggio più lento.
  5. Generazione della risposta: l'applicazione renderizza la risposta HTML (o JSON) da template, alberi di componenti o logica di serializzazione.

Ognuno di questi passaggi aggiunge tempo. Un server ben ottimizzato completa l'intera catena in meno di 100ms. Uno mal ottimizzato può impiegare 800ms o più, e questo prima ancora che DNS, connessione e latenza di rete entrino in gioco.

Come Misurare la Request Duration con l'API Server-Timing

L'header HTTP Server-Timing è il miglior strumento per diagnosticare la request duration. Ti permette di inviare le scomposizioni temporali dal server direttamente al browser, dove appaiono nei DevTools e sono accessibili tramite la Performance API. Questo significa che puoi misurare i singoli passaggi (query al database, rendering dei template, ricerche nella cache) e vedere esattamente cosa è lento.

Il formato dell'header Server-Timing è:

Server-Timing: db;dur=53.2;desc="Database queries",
               app;dur=24.1;desc="Application logic",
               tpl;dur=18.7;desc="Template rendering"

Questi valori appaiono nel pannello Network dei Chrome DevTools sotto la scheda "Timing", offrendoti un waterfall lato server che si mappa direttamente al tuo codice.

Server-Timing in PHP

La funzione hrtime(true) di PHP fornisce una precisione al nanosecondo, rendendola ideale per misurare le singole operazioni lato server. Ecco come aggiungere Server-Timing a un'applicazione PHP:

// Measure database query time with nanosecond precision
$dbStart = hrtime(true);
$result = $pdo->query('SELECT * FROM products WHERE active = 1');
$dbDuration = (hrtime(true) - $dbStart) / 1e6; // Convert to ms

// Measure template rendering
$tplStart = hrtime(true);
$html = renderTemplate('product-list', ['products' => $result]);
$tplDuration = (hrtime(true) - $tplStart) / 1e6;

// Send Server-Timing header to the browser
header(sprintf(
    'Server-Timing: db;dur=%.1f;desc="Database", tpl;dur=%.1f;desc="Template"',
    $dbDuration,
    $tplDuration
));

Server-Timing in Node.js / Express

In Node.js, usa process.hrtime.bigint() per il timing ad alta risoluzione. Un pattern a middleware ti permette di misurare il tempo totale di elaborazione della richiesta e le singole operazioni:

// Express middleware for Server-Timing headers
app.use((req, res, next) => {
  const start = process.hrtime.bigint();
  const timings = [];

  // Attach a helper to the response object
  res.serverTiming = (name, desc) => {
    const mark = process.hrtime.bigint();
    return () => {
      const dur = Number(process.hrtime.bigint() - mark) / 1e6;
      timings.push(`${name};dur=${dur.toFixed(1)};desc="${desc}"`);
    };
  };

  // Before sending the response, add the header
  const originalEnd = res.end.bind(res);
  res.end = (...args) => {
    const total = Number(process.hrtime.bigint() - start) / 1e6;
    timings.push(`total;dur=${total.toFixed(1)};desc="Total"`);
    res.setHeader('Server-Timing', timings.join(', '));
    originalEnd(...args);
  };

  next();
});

// Usage in a route handler
app.get('/products', async (req, res) => {
  const endDb = res.serverTiming('db', 'Database');
  const products = await db.query('SELECT * FROM products');
  endDb();

  const endTpl = res.serverTiming('tpl', 'Template');
  const html = renderTemplate('products', { products });
  endTpl();

  res.send(html);
});

Colli di Bottiglia Comuni nella Request Duration

Dopo aver strumentato centinaia di server, vedo gli stessi colli di bottiglia ripetersi continuamente. Ecco le cause più comuni di request duration lenta, classificate per frequenza con cui le incontro:

  • Query al database lente: query senza indici, pattern N+1, scansioni complete di tabelle di grandi dimensioni. Questa è la causa numero uno. Un singolo indice mancante su una tabella prodotti WooCommerce può aggiungere da 300 a 500ms per richiesta.
  • Mancanza di page caching: rigenerare lo stesso HTML per ogni visitatore quando il contenuto non è cambiato. Questo è particolarmente comune sui siti WordPress senza un object cache o un plugin di page cache.
  • Computazioni costose: eseguire calcoli complessi, elaborazione di immagini o aggregazione di dati ad ogni richiesta invece di memorizzare i risultati nella cache.
  • Chiamate API esterne: richieste sincrone verso API di terze parti (gateway di pagamento, sistemi CRM, servizi di inventario) che bloccano la risposta fino al completamento.
  • Codice applicativo non ottimizzato: caricamento di moduli non utilizzati, esecuzione di middleware non necessari o utilizzo di algoritmi inefficienti per l'elaborazione dei dati.
  • Cold start: sulle piattaforme serverless (AWS Lambda, Cloudflare Workers, Vercel Functions), la prima richiesta dopo un periodo di inattività comporta un overhead di inizializzazione del container.

Soluzioni Specifiche per Piattaforma

WordPress

I siti WordPress sono particolarmente vulnerabili a una request duration lenta perché ogni caricamento di pagina esegue il bootstrap dell'intero core di WordPress, di tutti i plugin attivi e del tema. Ecco cosa fa la maggiore differenza:

  • Installare un object cache persistente: Redis o Memcached. WordPress esegue decine di query al database per caricamento di pagina, molte delle quali identiche tra i visitatori. Un object cache (tramite un plugin come Redis Object Cache) memorizza questi risultati in memoria, riducendo il tempo del database dal 60 all'80%.
  • Abilitare il full-page caching: usa una page cache a livello di server (Nginx FastCGI Cache, Varnish) o un plugin come WP Super Cache. Questo serve HTML memorizzato nella cache direttamente senza toccare PHP.
  • Verificare i plugin lenti: usa il plugin Query Monitor per identificare quali plugin generano il maggior numero di query al database o consumano il maggior tempo di esecuzione PHP.
  • Ottimizzare le query di WooCommerce: WooCommerce è noto per le query sui prodotti lente. Abilita la funzionalità High-Performance Order Storage (HPOS) e aggiungi gli indici di database appropriati alla tabella wp_postmeta.

Caso studio: Un sito WordPress ha ridotto la request duration da 800ms a 120ms implementando l'object caching (Redis) e ottimizzando una query lenta sui prodotti WooCommerce che veniva eseguita ad ogni caricamento di pagina. La sola query sui prodotti rappresentava 450ms perché stava eseguendo una scansione completa della tabella su 80.000 righe di postmeta senza un indice.

Node.js

Le applicazioni Node.js hanno tipicamente una request duration veloce di base, ma i problemi appaiono con la scalabilità o con operazioni bloccanti:

  • Profilare con l'inspector integrato: esegui node --inspect app.js e connetti Chrome DevTools per identificare le funzioni ad alto consumo di CPU. Cerca operazioni sincrone che bloccano l'event loop.
  • Abilitare il logging delle query ORM: se usi Sequelize, Prisma o TypeORM, abilita il logging delle query per trovare pattern N+1 e query lente. In Sequelize: sequelize = new Sequelize({ logging: console.log }).
  • Usare il connection pooling: non creare una nuova connessione al database per ogni richiesta. Usa un pool di connessioni (integrato nella maggior parte dei driver database Node.js) per riutilizzare le connessioni.
  • Implementare il caching in memoria: per i dati frequentemente acceduti che non cambiano spesso, usa una cache LRU per evitare di interrogare il database ad ogni richiesta.

PHP (non-WordPress)

Per applicazioni Laravel, Symfony o PHP personalizzate:

  • Abilitare OPcache: OPcache di PHP compila gli script PHP in bytecode e li memorizza nella memoria condivisa, eliminando la necessità di analizzare e compilare ad ogni richiesta. Questo da solo può ridurre la request duration dal 30 al 50%.
  • Usare un preloader di bytecode: PHP 8.0+ supporta il preloading (disponibile da PHP 7.4), che carica i file del framework in memoria all'avvio del server in modo che non debbano essere caricati per ogni richiesta.
  • Profilare con Xdebug o Blackfire: identifica le funzioni specifiche che consumano il maggior tempo di esecuzione.

Python (Django / Flask)

Le applicazioni Python hanno spesso una request duration di base più alta rispetto a Node.js o PHP:

  • Usare un framework asincrono: se l'attesa di I/O è il collo di bottiglia, considera FastAPI o Django con ASGI per gestire query al database e chiamate API in modo concorrente.
  • Abilitare il logging delle query del database di Django: imposta LOGGING nelle impostazioni per registrare tutte le query SQL e identificare quelle lente o ridondanti.
  • Usare select_related() e prefetch_related(): l'ORM di Django genererà allegramente query N+1 a meno che non gli dici esplicitamente di fare il join delle tabelle correlate.

Connection Pooling del Database

Aprire una nuova connessione al database per ogni richiesta è una delle cause più comuni, e più evitabili, di request duration lenta. Ogni nuova connessione richiede l'handshake TCP, l'autenticazione e l'inizializzazione della sessione, il che può aggiungere da 5 a 30ms per richiesta. Sotto carico, questo diventa catastrofico poiché il server del database esaurisce le connessioni disponibili.

Il connection pooling risolve questo problema mantenendo un pool di connessioni aperte che vengono riutilizzate tra le richieste. L'applicazione prende in prestito una connessione dal pool, esegue le sue query e restituisce la connessione quando ha finito. Questo elimina completamente l'overhead di connessione per richiesta.

La maggior parte dei driver di database supporta il connection pooling nativamente. In Node.js con pg (PostgreSQL), ad esempio, configuralo in questo modo:

const { Pool } = require('pg');

const pool = new Pool({
  host: 'localhost',
  database: 'myapp',
  max: 20,        // Maximum connections in the pool
  idleTimeoutMillis: 30000,  // Close idle connections after 30s
  connectionTimeoutMillis: 2000  // Fail fast if no connection available
});

// Use pool.query() instead of creating new clients
const result = await pool.query('SELECT * FROM products WHERE id = $1', [id]);

Per le applicazioni PHP dietro PHP-FPM, considera l'utilizzo di connessioni persistenti (PDO::ATTR_PERSISTENT) o di un pooler esterno come PgBouncer per PostgreSQL o ProxySQL per MySQL.

Reverse Proxy Caching

La risposta più veloce è quella che la tua applicazione non deve mai generare. Una reverse proxy cache (Varnish, Nginx FastCGI Cache o una CDN edge cache) si posiziona davanti al tuo application server e serve le risposte memorizzate nella cache direttamente dalla memoria. Per le pagine che non cambiano tra i visitatori (che includono la maggior parte delle pagine nella maggior parte dei siti web) questo porta la request duration vicina allo zero.

  • Varnish: una cache HTTP dedicata che può servire migliaia di richieste al secondo dalla memoria. Configura gli header Cache-Control nelle risposte della tua applicazione e Varnish si occupa del resto.
  • Nginx FastCGI Cache: se utilizzi già Nginx come web server, abilita il caching integrato per le risposte PHP-FPM. Questo evita di aggiungere un ulteriore livello al tuo stack.
  • CDN edge caching: servizi come Cloudflare, Fastly e Amazon CloudFront possono memorizzare nella cache il tuo HTML nelle posizioni edge in tutto il mondo, riducendo sia la request duration che la latenza di rete simultaneamente.

La chiave per un reverse proxy caching efficace sono gli header Cache-Control appropriati. Imposta s-maxage per il TTL della cache condivisa e usa stale-while-revalidate per servire contenuti obsoleti mentre la cache viene aggiornata in background:

Cache-Control: public, s-maxage=3600, stale-while-revalidate=60

Edge Computing per la Request Duration

Le piattaforme di edge computing come Cloudflare Workers e Vercel Edge Functions eseguono il codice lato server nelle posizioni CDN edge, fisicamente vicine ai tuoi utenti. L'edge computing non renderà il tuo codice più veloce, ma elimina la latenza di rete tra l'utente e il tuo server di origine. Questo conta di più per gli utenti lontani dal tuo data center di origine.

Le edge function funzionano meglio per:

  • Risposte API leggere che non richiedono accesso pesante al database
  • Logica di personalizzazione (A/B testing, contenuto basato sulla geolocalizzazione) applicata all'edge prima di raggiungere l'origine
  • Riscritture HTML e manipolazione degli header senza un viaggio completo di andata e ritorno verso l'origine

Per le pagine che richiedono query al database, l'edge computing da solo non risolverà i problemi di request duration. Il vero vantaggio è combinare le edge function con un database distribuito globalmente (PlanetScale, Neon, Turso) o il caching edge-side per mantenere l'intero ciclo di vita della richiesta vicino all'utente.

Misurare la Request Duration con JavaScript

Puoi misurare la sotto-parte request duration del TTFB direttamente nel browser usando la Navigation Timing API:

new PerformanceObserver((entryList) => {
  const [nav] = entryList.getEntriesByType('navigation');

  const requestDuration = nav.responseStart - nav.requestStart;

  console.log('Request Duration:', requestDuration.toFixed(0), 'ms');
  console.log('  Request start:', nav.requestStart.toFixed(0), 'ms');
  console.log('  Response start:', nav.responseStart.toFixed(0), 'ms');

  if (requestDuration > 200) {
    console.warn('Slow request duration detected. Check server processing time.');
  }
}).observe({
  type: 'navigation',
  buffered: true
});

La request duration è calcolata come responseStart - requestStart. Un valore costantemente superiore a 200ms indica che il tuo server sta impiegando troppo tempo per elaborare la richiesta. Usa l'header Server-Timing (descritto sopra) per identificare quale parte dell'elaborazione del server è responsabile.

Come Identificare i Problemi di Request Duration con i Dati RUM

Per capire come la request duration impatta i tuoi utenti reali, hai bisogno di uno strumento di Real User Monitoring (RUM) come CoreDash. I dati RUM mostrano l'effettiva scomposizione del TTFB che i tuoi visitatori sperimentano attraverso pagine, dispositivi e posizioni. Non risultati di laboratorio.

In CoreDash, clicca su "Time to First Byte breakdown" per visualizzare la porzione request duration del TTFB. Cerca le pagine dove la request duration è costantemente superiore a 200ms. Quelle sono i tuoi obiettivi di ottimizzazione.

Cosa Mostrano i Nostri Dati

Tra migliaia di siti monitorati da CoreDash, la request duration (tempo di elaborazione del server) è la sotto-parte più grande del TTFB nella maggior parte dei siti nel nostro dataset, rendendo l'ottimizzazione del server il singolo più grande miglioramento del TTFB per la maggior parte dei siti web.

I siti con full-page caching abilitato hanno una request duration mediana di circa 35ms. I siti senza alcun caching hanno una mediana di circa 320ms. Quel divario (quasi 10 volte) è l'argomento più forte che posso fare per investire nel caching lato server prima di qualsiasi altra cosa.

La request duration è parte del Time to First Byte, che è una metrica diagnostica per i Core Web Vitals. Per una guida completa all'identificazione e alla risoluzione dei problemi di TTFB, consulta la nostra guida per identificare e risolvere il TTFB. Puoi anche consultare la lista di verificazione definitiva dei Core Web Vitals per una panoramica completa sull'ottimizzazione.

Approfondimenti: Guide all'Ottimizzazione

Per tecniche di ottimizzazione correlate che completano l'ottimizzazione della request duration, esplora queste guide:

  • 103 Early Hints: invia resource hints (preload, preconnect) al browser mentre il server sta ancora elaborando la richiesta, riducendo il TTFB percepito.
  • Configurare Cloudflare per le Prestazioni: usa il CDN edge caching e configurazioni server ottimizzate per ridurre la request duration a livello globale.

Sotto-parti del TTFB: Guide Complete

La request duration è una delle cinque sotto-parti del TTFB. Esplora le altre sotto-parti per comprendere il quadro completo:

I have done this before at your scale.

Complex platforms, large dev teams, legacy code. I join your team as a specialist, run the performance track, and hand it back in a state you can maintain.

Discuss Your Situation
TTFB Request Duration: Ridurre il Tempo di Elaborazione del ServerCore Web Vitals TTFB Request Duration: Ridurre il Tempo di Elaborazione del Server