WordPress lento: come capire in 10 minuti se il collo di bottiglia è il server
Tre livelli, sei test con curl, Query Monitor, slow log e PHP-FPM, e una tabella che dice dove sta il collo di bottiglia. Poi chi lo risolve: il sito o il server.

"Il sito è lento" è la frase con cui iniziano metà dei ticket, e finiscono con due risposte che non aiutano: "il server è operativo" dal provider, "è l'hosting" dallo sviluppatore. Nessuno dei due ha misurato. Questa guida chiude la discussione in dieci minuti con numeri, e manda il problema al mestiere giusto: chi gestisce il sito o chi gestisce il server.
Quali sono i tre livelli in cui WordPress perde tempo?
- Rete e TTFB: DNS, connessione, TLS e il tempo che il server impiega a iniziare la risposta. Si misura da fuori, con curl.
- Server: PHP-FPM e database: worker PHP disponibili, OPcache, memoria e disco, MySQL con il suo buffer pool. Si misura da dentro, con accesso alla macchina o al pannello.
- Tema e plugin: il codice che gira a ogni richiesta, le query che genera, le chiamate HTTP che fa. Si misura con Query Monitor.
La regola: si parte dal livello 1 e si scende solo se i numeri lo dicono. La sequenza completa di priorità è nella guida sull'ordine giusto della diagnosi; qui interessa una domanda sola: sito o server.
Come si misura il TTFB in modo che dica qualcosa?
Un TTFB da solo non distingue niente. Scomposto sì:
curl -s -o /dev/null -w "dns=%{time_namelookup} tcp=%{time_connect} tls=%{time_appconnect} ttfb=%{time_starttransfer} totale=%{time_total}\n" https://iltuosito.it/
Lettura:
tcpetlsalti (oltre 200-300 ms dall'Italia verso un server europeo): rete, DNS o un server che fatica ad accettare connessioni. Livello 1.ttfbmenotlsalto: il tempo lo passa il server a costruire la pagina. Da qui in poi si decide tra livello 2 e 3.
Ripeti tre volte e in due momenti della giornata: un valore che oscilla molto tra una misura e l'altra indica contesa di risorse (livello 2), un valore stabile e alto indica codice (livello 3). La lettura estesa del dato è nella diagnosi TTFB.
Qual è il test che separa il sito dal server?
Pagina statica contro pagina PHP. Misura un file che non passa da PHP, poi una pagina che ci passa per forza, poi la stessa pagina servita dalla cache:
# file statico servito dal web server, niente PHP
curl -s -o /dev/null -w "statico ttfb=%{time_starttransfer}\n" https://iltuosito.it/wp-includes/js/jquery/jquery.min.js
# pagina PHP forzando il miss di cache
curl -s -o /dev/null -w "php ttfb=%{time_starttransfer}\n" "https://iltuosito.it/?nocache=$(date +%s)"
# la stessa pagina dalla cache: guarda l'header di hit
curl -sI https://iltuosito.it/ | grep -iE "x-cache|cf-cache-status|x-litespeed-cache|^age:"
- Statico lento (sopra 200-300 ms): il server o la rete sono lenti prima ancora di WordPress. Disco, web server saturo, macchina condivisa sovraffollata. Livello 1 o 2, in ogni caso non il tema.
- Statico veloce, cache HIT lenta: il server fa fatica a servire perfino una risposta pronta. Livello 2.
- Statico veloce, HIT veloce, MISS lento: il costo è nella generazione della pagina. Può essere PHP-FPM saturo (livello 2) o codice pesante (livello 3): lo decidono i prossimi due test.
Cosa guardare in Query Monitor per capire se è il codice?
Query Monitor è gratuito e va attivato sul sito, meglio su staging o in orario di basso traffico. Nella barra in alto trovi tempo totale, tempo PHP, tempo database e numero di query. La lettura:
- Tempo DB alto con poche query lente dello stesso chiamante: un plugin o il tema fanno query pesanti. Livello 3, sito.
- Tempo DB alto con tutte le query lente, anche quelle banali: MySQL è affamato di memoria o di disco. Livello 2, server.
- Tempo PHP alto con tempo DB basso: codice che macina, oppure OPcache che non trattiene i file. Guarda la scheda delle chiamate HTTP API: una chiamata esterna sincrona (verifica licenze, feed, font) da due secondi è un classico del livello 3.
- Centinaia di query per pagina: sito, quasi sempre un plugin di related posts, un widget social o un builder che carica tutto.
Quali numeri del server chiudono la diagnosi?
Servono accesso SSH o un pannello che li esponga. Quattro comandi, un minuto ciascuno (i percorsi dei log cambiano con la distribuzione):
# 1. load rispetto ai core
uptime; nproc
# 2. worker PHP attivi e volte in cui il limite è stato raggiunto
ps -eo comm | grep -c php-fpm
grep -c "max_children" /var/log/php*fpm*.log
# 3. memoria, swap, CPU rubata e iowait
free -m; vmstat 1 5
# 4. MySQL: buffer pool e slow log
mysql -e "SHOW GLOBAL VARIABLES LIKE 'innodb_buffer_pool_size'; SHOW GLOBAL STATUS LIKE 'Innodb_buffer_pool_read%'; SHOW GLOBAL VARIABLES LIKE 'slow_query_log%';"
Come leggerli:
- load stabilmente sopra il numero di core e
vmstatcon la colonnarpiena: CPU contesa. Su hosting condiviso guarda anchest(steal): se supera il 5-10 percento, la macchina fisica è sovraffollata e nessun tuning del sito lo risolve. - "server reached pm.max_children setting" nel log di PHP-FPM: i worker sono finiti e le richieste si mettono in coda. È il caso più frequente di "lento a scatti" e non ha niente a che fare con il tema.
- swap in uso o
wa(iowait) alto: memoria insufficiente o disco lento, spesso i due insieme. Innodb_buffer_pool_readsche cresce rispetto aInnodb_buffer_pool_read_requests: MySQL legge da disco perché il buffer pool è più piccolo dei dati. Con un buffer pool sotto il gigabyte su un WooCommerce medio è quasi certo.- slow log spento: nessuno ha mai guardato le query. Attivalo con
long_query_time=1per un'ora e leggi il risultato conmysqldumpslow -s t. - OPcache: va letta dal processo PHP-FPM, non dalla CLI, che ha una cache separata (con
cachetool opcache:statuso una pagina temporanea che stampaopcache_get_status()).num_cached_keysvicino amax_cached_keysooom_restartssopra zero significa che i file PHP vengono ricompilati di continuo: un sito con molti plugin ha decine di migliaia di file, il defaultopcache.max_accelerated_filesè pensato per quattromila. - wp-cron a ogni visita:
grep -c wp-cron.php access.lognelle ultime ore. Se compare a ogni richiesta e ci sono decine di eventi in coda, ogni utente paga il lavoro di sfondo. Si sposta su cron di sistema conDISABLE_WP_CRON.
Se vedi X, il collo è Y
| Se vedi | Il collo è | Livello | Chi interviene |
|---|---|---|---|
tcp o tls sopra 300 ms | Rete, DNS o server che non accetta connessioni | 1 | Server |
| File statico lento | Disco, web server, macchina condivisa satura | 1-2 | Server |
| Cache HIT lenta | Server in sofferenza anche a costo zero | 2 | Server |
| "max_children" nel log PHP-FPM | Worker PHP esauriti | 2 | Server |
Load sopra i core, st alto | CPU contesa, hosting sovraffollato | 2 | Server (o cambio piano) |
Innodb_buffer_pool_reads in crescita | Buffer pool sottodimensionato | 2 | Server |
| OPcache piena o con restart | OPcache sottodimensionata | 2 | Server |
| Tutte le query lente, anche banali | MySQL affamato di risorse | 2 | Server |
| Poche query lente, stesso chiamante | Plugin o tema con query pesanti, indici mancanti | 3 | Sito |
| Chiamata HTTP esterna nel tempo PHP | Plugin con verifica remota sincrona | 3 | Sito |
| Centinaia di query per pagina | Plugin o builder | 3 | Sito |
| wp-cron a ogni richiesta | Cron di WordPress non disaccoppiato | 2-3 | Sito + server |
| TTFB ok, LCP alto | Immagini, script, font: non è il server | 3 | Sito |
L'ultima riga merita una nota: immagini non ottimizzate e JavaScript del tema non toccano il TTFB. Se il tuo problema è il rendering, il server non c'entra e il percorso è quello dei Core Web Vitals.
Cosa chiedere al provider, e cosa vuol dire "il server è operativo"?
"Il server è operativo" vuol dire che la macchina risponde al ping, i servizi girano e non ci sono guasti hardware. Non dice nulla sui worker PHP del tuo account, sulla dimensione del buffer pool, sul disco condiviso con altri cento siti. È una frase vera e inutile.
Chiedi numeri, non aggettivi:
- quanti worker PHP ha il mio account (o il mio pool) e quante volte nelle ultime 24 ore è stato raggiunto il limite;
- il load medio della macchina e il numero di core;
- se il mio account ha toccato i limiti di CPU, memoria, I/O o processi (su CloudLinux si vede in "Utilizzo risorse");
- la dimensione di
innodb_buffer_pool_sizee se lo slow log è attivo; - il tipo di disco e la percentuale di utilizzo.
Se la risposta è "tutto regolare" senza un numero, hai già la risposta: quel livello non lo gestisce nessuno.
Se è il server, chi lo mette a posto?
Il perimetro conta più dello strumento. Del sito si occupa WPsec.it: query di plugin e tema, cache, autoload di wp_options, chiamate esterne, cron di WordPress, immagini e rendering. Il servizio corrispondente è velocizzare WordPress, con la scheda tecnica in ottimizzazione performance: misura prima e dopo, verifica di integrità inclusa, perché un sito lento perché infetto non si ottimizza, si bonifica. I costi sono nella pagina prezzi.
Del server si occupa managedvps.it, il servizio della stessa squadra tecnica dedicato alla macchina Linux: PHP-FPM, OPcache, MySQL, disco, memoria, web server. Se i test ti hanno portato al livello 2 e non hai un sistemista, la diagnosi e ottimizzazione lato server è l'intervento una tantum; la gestione del server è il caso in cui vuoi che quei numeri li guardi qualcuno anche il mese prossimo.
Se sei su hosting condiviso il livello 2 non è tuo: puoi solo chiedere i numeri al provider e, se non arrivano, cambiare piano. Con i test qui sopra almeno lo fai sapendo cosa stai comprando.
Come faccio a capire se WordPress è lento per colpa del server o del sito?
Misura un file statico e una pagina PHP con curl. Se anche il file statico è lento, è il server o la rete. Se il file vola e la pagina PHP è lenta, apri Query Monitor: query pesanti di un solo plugin o chiamate esterne indicano il sito; tutte le query lente, worker PHP esauriti o load sopra i core indicano il server.
Quanto deve essere il TTFB di un sito WordPress?
Sotto 200 ms per una pagina servita dalla cache, entro 500-600 ms per una pagina dinamica su un server sano. Oltre 800 ms c'è un problema strutturale: cache assente, worker PHP saturi, database sottodimensionato o un plugin pesante. Il valore da solo non basta: va scomposto in connessione, TLS e tempo di generazione.
Cambiare hosting risolve un WordPress lento?
Solo se il collo è al livello 2 e il nuovo piano ha davvero più worker PHP, più memoria per MySQL e un disco migliore. Un plugin che fa 400 query per pagina resta lento anche sul server più costoso. Misura prima con i test di questa guida: se il problema è il codice, il cambio hosting è una spesa senza effetto.
Cosa vuol dire quando il provider risponde che il server è operativo?
Che la macchina risponde e i servizi sono attivi. Non dice nulla sui limiti del tuo account, sui worker PHP, sul buffer pool di MySQL o sul disco condiviso. Chiedi numeri precisi: worker e volte in cui il limite è stato raggiunto, load e core, limiti toccati, dimensione del buffer pool, tipo di disco.
Scritto dal team WPsec.it
Team WPsec.it
Bonifica malware, hardening, performance e manutenzione WordPress.
Prevenzione e gestione
Dopo l'emergenza, o per non arrivarci: le guide sulla gestione.
Sicurezza, velocità e manutenzione di WordPress sono lo stesso lavoro visto da tre lati. Queste pagine spiegano cosa controllare, con quale priorità e quanto costa farlo fare.
Continua a leggere
Articoli correlati.

WordPress lento: diagnosi TTFB prima di installare altri plugin
Se WordPress è lento, partire dal TTFB evita interventi inutili. Come leggere server response time, hosting, database, cache e plugin.

WordPress non è lento: la diagnosi che quasi nessuno fa nell'ordine giusto
Cambiare hosting, installare cache, ottimizzare le immagini: la maggior parte degli interventi di velocizzazione parte dal punto sbagliato. L'ordine corretto di diagnosi delle performance WordPress che evita spese inutili.

Il tuo sito è lento perché è infetto: il malware come causa nascosta delle performance
Cache ottimizzata, immagini compresse, hosting cambiato, e il sito continua a rallentare. Una causa raramente considerata: il malware consuma risorse e degrada le performance prima ancora di mostrare sintomi visibili.