Il tuo sito WordPress ha un TTFB di 200 millisecondi alle 10 del mattino, ma alle 14 — quando parte il cron di import prodotti del tuo grossista — schizza a 4-8 secondi per 20 minuti. Il cliente medio non se ne accorge, ma il cliente che in quei 20 minuti tenta il checkout vede una pagina che gira a vuoto e abbandona il carrello. Il cron "invisibile" ti costa conversioni ogni singolo giorno.
In WP-Cron WordPress: ottimizzare i task background in produzione abbiamo affrontato il lato "come configurare WP-Cron correttamente in produzione" — disabilitare lo spawn nativo, spostare su cron di sistema, gestire WP-CLI. Ma quel setup da solo non basta. Il 2026 ha reso il problema molto più visibile: import massivi WooCommerce, backup incrementali, e scan di sicurezza AI-assisted competono per risorse condivise con il traffico utente in modo che fino al 2024 era trascurabile. Oggi non lo è più.
Contenuto articolo
- Il problema invisibile che nessuno misura
- Le 5 metriche che devi monitorare
- Il framework: il "background activity budget"
- Il caso studio WooCommerce da 12.000 SKU
- Le 3 trappole che il team WordPress medio non vede
- Come questo si collega agli articoli precedenti della serie
- Domande frequenti
- È possibile eliminare del tutto i cron WordPress?
- Come faccio a sapere se un cron specifico sta degradando le performance?
- È meglio WP-Cron o cron di sistema?
- I plugin di cache aiutano anche per i cron?
- Quando serve un hosting dedicato per i cron pesanti?
- Lo scan AI di Wordfence rallenta davvero il sito?
- Checklist operativa per i prossimi 14 giorni
- Riferimenti utili per approfondire
Il problema invisibile che nessuno misura
Un cron WordPress — qualunque esso sia, sia esso pianificato via WP-Cron sia eseguito da cron di sistema con wp cron event run — fa una cosa semplice dal punto di vista logico: esegue codice PHP. Ma dal punto di vista del sistema operativo quel codice PHP deve passare attraverso lo stesso stack di qualsiasi richiesta web:
# catena di esecuzione di un cron job su WordPress
1. PHP binary avviato (o php-fpm worker riservato)
2. WordPress core caricato (~80-150 MB RAM)
3. Plugin attivi caricati (ognuno aggiunge overhead)
4. Connessione database aperta
5. Eventuale cache object (Redis/Memcached) collegata
6. Codice del cron eseguito
7. Risultato persistito (DB/scritture filesystem)
Anche un cron leggero come wp cron event run due_action consuma 60-100 MB di RAM per i 200-400 millisecondi che dura. Un cron pesante come un import WooCommerce da CSV di 10.000 prodotti dura 20-45 minuti e consuma costantemente 150-250 MB.
Il punto critico non è il consumo di per sé. È che quel PHP-FPM worker — o quel processo PHP-CLI — compete per le stesse risorse del tuo web server:
- CPU: il job usa cicli che potrebbero servire a servire il checkout di un cliente.
- Database connection pool: MySQL ha un limite di connessioni concorrenti (default 151). Un cron pesante che ne apre 5-10 ruba slot al traffico web.
- I/O disco: scritture su
wp_options,wp_postmeta, file uploads competono con la cache page su disco. - PHP-FPM pool: se il cron passa per php-fpm (impostazione sbagliata ma comune), sottrae worker al web server.
Su un sito WooCommerce con 50 PHP-FPM worker disponibili, un cron di import che passa per php-fpm e ne occupa 10-15 contemporaneamente riduce il pool effettivo a 35-40 — esattamente il punto in cui, nei momenti di punta, la saturazione ricomincia. È la stessa dinamica dei bot AI che abbiamo analizzato in WordPress PHP thread 2026: come i bot AI li stanno esaurendo, solo che stavolta il "bot" è un tuo job interno.
Le 5 metriche che devi monitorare
Il framework operativo si basa su 5 metriche misurabili, tutte ricavabili da strumenti standard di un server WordPress gestito ragionevolmente.
Metrica 1: TTFB p95 durante i cron
Il Time To First Byte al 95° percentile è la metrica più diretta: misura il tempo di risposta del web server sotto carico. Quando un cron pesante parte, il TTFB p95 del sito live sale.
# script: misura TTFB p95 da log Nginx
# (assumendo log formato combined)
awk '{print $4, $7, $NF}' /var/log/nginx/access.log | awk '$4 ~ /\[.*:[0-9]+:[0-9]+:[0-9]+\]/ {match($4, /\[([^:]+):([^:]+):([^:]+):([^:]+)/, t); time_bucket = t[1]" "t[2]":"substr(t[3],1,2); ttfb = $NF; if (ttfb ~ /^[0-9.]+$/) print time_bucket, ttfb}' | sort | awk '{sum += $2; n++; arr[n]=$2; time=$1} END {print time, arr[int(n*0.95)]}'
Salvalo come /usr/local/bin/ttfb-p95-monitor.sh e fanne un cron ogni 5 minuti. Quando il valore sale sopra i 500 ms, hai un cron che sta impattando le performance.
Metrica 2: durata effettiva dei cron job
WP-CLI ti dice esattamente quanto dura un evento:
# misura durata effettiva di un evento cron
time wp cron event run your_heavy_event --allow-root --path=/var/www/html
Output tipo: real 3m42.115s — il tuo import sta durando 3 minuti e 42 secondi. Se lo esegui ogni ora, hai un throughput continuo di background activity che erode la capacità di picco per il traffico live.
Metrica 3: lock contention sul database
MySQL ha una metrica interna che ti dice se i tuoi cron stanno litigando con le query live per i lock sulle tabelle:
# controlla lock contention
mysql -u root -p -e "SHOW ENGINE INNODB STATUS\G" | grep -E "LATEST DETECTED DEADLOCK|LOCK WAIT TIMEOUT|Semaphore"
Se vedi deadlock o lock wait frequenti sulle tabelle wp_options, wp_postmeta, wp_wc_orders, il colpevole è quasi certamente un cron che scrive molto mentre il sito live sta cercando di leggere.
Metrica 4: disk I/O wait
Quando un cron scrive molto (import massivi, backup, rigenerazione miniature), il disco si satura e tutte le altre operazioni rallentano:
# controlla I/O wait
iostat -x 1 5 | awk '/^avg-cpu:/ {getline; print "iowait:", $4"%"}'
iowait > 20% durante un cron è segnale che il disco sta diventando il collo di bottiglia. Su hosting con storage di rete (EBS, NFS), questo è ancora più marcato.
Metrica 5: PHP-FPM queue length
L'ultima metrica è la lunghezza della coda di processi PHP in attesa. Quando la coda si riempie, i visitatori reali aspettano:
# monitor coda php-fpm
curl -s "YOUR_PHP_FPM_STATUS_ENDPOINT" | python3 -c "import json,sys; d=json.load(sys.stdin); print(f"listen_queue={d.get('listen queue', 0)} max_listen_queue={d.get('max listen queue', 0)} active={d['active processes']}/{d['max active processes']}")"
Se listen_queue > 0 per più di 30 secondi consecutivi, hai un problema di capacity che potrebbe essere causato da un cron o da traffico bot AI (o da entrambi, come abbiamo visto nell'articolo precedente).
Il framework: il "background activity budget"
La soluzione non è "vietare i cron pesanti" — i cron sono necessari. La soluzione è dargli un budget operativo misurabile.
Passo 1: definisci il tuo budget
Il budget è definito da tre vincoli:
CPU consentita background: max 30% di 1 core durante i job
RAM consentita background: max 25% della RAM totale
PHP-FPM workers sottratti: max 15% del pool
I/O wait aggiuntivo ammesso: max 10% sopra il baseline live
Questi numeri sono conservativi per un sito WooCommerce di medie dimensioni. Su un sito editoriale con traffico di picco notturno puoi permetterti budget più alti nelle ore diurne e più bassi nelle ore di punta.
Passo 2: schedula i cron pesanti nelle finestre a basso traffico
L'errore più comune è eseguire import massivi alle 14:00 perché "il sistema è libero a quell'ora". Ma il sistema è libero a quell'ora solo perché alle 14:00 non c'è molto traffico, non perché il sistema può permettersi di degradare quello che c'è.
# sposta i cron pesanti in finestre a basso traffico (2-5 del mattino per ecommerce IT)
# /etc/cron.d/wordpress-imports
0 2 * * * www-data cd /var/www/html && /usr/local/bin/wp cron event run woo_import_daily --allow-root >> /var/log/wp-cron-imports.log 2>&1
0 3 * * * www-data cd /var/www/html && /usr/local/bin/wp cron event run woo_sync_stock --allow-root >> /var/log/wp-cron-imports.log 2>&1
0 4 * * * www-data cd /var/www/html && /usr/local/bin/wp cron event run woo_regenerate_thumbs --allow-root >> /var/log/wp-cron-imports.log 2>&1
Ma non basta spostarli di notte: devi anche limitare la concorrenza interna al job.
Passo 3: limita la concorrenza interna dei cron pesanti
Molti plugin (specialmente quelli di import) permettono di configurare batch size e pausa tra batch. Settare batch_size = 50 con pause_between = 2 seconds invece di batch_size = 500 con pausa zero riduce il picco di carico del 60-70% allungando la durata del 20%.
Per WooCommerce il pattern canonico è:
// imposta batch size conservativo per WooCommerce product import
add_filter('woocommerce_product_import_batch_size', function() {
return 25; // prodotti per batch
});
add_filter('woocommerce_product_import_pause_between_batches', function() {
return 2; // secondi tra batch
});
Passo 4: isola i cron pesanti dal web server
Se il tuo hosting lo permette, esegui i cron pesanti in un container o in un processo PHP-CLI separato dal web server, con il proprio database connection pool:
# esegui cron pesante via PHP-CLI (non via php-fpm)
# questo NON sottrae worker al web server
time php /var/www/html/wp-cron.php your_heavy_event
La differenza è enorme: php-fpm è progettato per gestire molte richieste brevi, non per un singolo job che dura 20 minuti. PHP-CLI è progettato per il contrario. Mandare un cron di import via php-fpm è come usare un'auto da corsa per traslocare — possibile, ma altamente inefficiente.
Passo 5: monitora e allerta
Il monitoraggio continuo è l'unica cosa che impedisce al framework di diventare una configurazione-iniziale-e-poi-si-dimentica. Lo script di monitoraggio che segue controlla le 5 metriche e invia un alert se il budget viene sforato:
#!/bin/bash
# /usr/local/bin/background-budget-watch.sh
# Monitor background activity budget - invia alert se superato
STATE_FILE="/tmp/budget_state"
LOG="/var/log/budget-monitor.log"
WEBHOOK_URL="YOUR_SLACK_OR_TELEGRAM_WEBHOOK"
# Misura I/O wait
IO_WAIT=$(iostat -x 1 2 | tail -1 | awk '{print $4}')
# Misura TTFB p95 ultimi 5 minuti (da log Nginx)
TTFB_P95=$(awk -v cutoff="$(date -d '5 minutes ago' +%H:%M:%S)" '$4 > "["cutoff {print $NF}' /var/log/nginx/access.log | sort -n | awk 'END{print arr[int(NR*0.95)]}')
# Misura processi cron attivi
CRON_ACTIVE=$(pgrep -fc "wp cron event run")
# Soglie
IO_LIMIT=20
TTFB_LIMIT=1.5
CRON_LIMIT=3
ALERTS=""
if (( $(echo "$IO_WAIT > $IO_LIMIT" | bc -l) )); then
ALERTS="$ALERTS\n- I/O wait: ${IO_WAIT}% > ${IO_LIMIT}%"
fi
if (( $(echo "$TTFB_P95 > $TTFB_LIMIT" | bc -l) )); then
ALERTS="$ALERTS\n- TTFB p95: ${TTFB_P95}s > ${TTFB_LIMIT}s"
fi
if [ "$CRON_ACTIVE" -gt "$CRON_LIMIT" ]; then
ALERTS="$ALERTS\n- Cron job attivi: $CRON_ACTIVE > $CRON_LIMIT"
fi
if [ -n "$ALERTS" ]; then
MSG="⚠️ Background activity budget superato ($(date))$ALERTS"
curl -s -X POST "$WEBHOOK_URL" -d "text=$MSG" >/dev/null
echo "$(date +%s) ALERT: $ALERTS" >> "$LOG"
fi
Aggiungi a crontab ogni 5 minuti:
# ogni 5 minuti controlla il budget
*/5 * * * * root /usr/local/bin/background-budget-watch.sh
Il caso studio WooCommerce da 12.000 SKU
Un cliente tipico — negozio WooCommerce con 12.000 SKU, import giornaliero dal grossista, 2.000 ordini/giorno, hosting managed con 40 PHP-FPM worker — presentava questo quadro a inizio 2026:
- TTFB p95 diurno: 180-220 ms (sano).
- TTFB p95 alle 14:00 (orario import): 4.800 ms (catastrofico).
- Tasso di abbandono carrello alle 14:00: 71% (vs 28% medio diurno).
- Stima revenue perso per degrado cron: circa 8.000€/mese.
Applicando il framework in 4 settimane:
- Spostato l'import da CSV alle 02:00 (finestra a traffico zero).
- Ridotto batch size da 500 a 25 prodotti con pausa 2 secondi.
- Migrato l'import da esecuzione via php-fpm a PHP-CLI con
wp cron event run. - Aggiunto monitoring budget con alert Slack quando TTFB p95 > 1.5s.
Risultato a 60 giorni:
- TTFB p95 alle 14:00: 210 ms (invariato rispetto al baseline).
- Tasso di abbandono carrello: tornato al 28% anche nelle ore post-import.
- Revenue recuperato stimato: ~8.000€/mese.
Il costo di queste 4 modifiche è stato di mezza giornata di lavoro di un dev senior. Il ROI è stato inferiore a una settimana.
Le 3 trappole che il team WordPress medio non vede
Trappola 1: il cron "importante" che gira 24/7
Plugin come WooCommerce Subscriptions, Yoast SEO, Wordfence oggi eseguono cron continui per aggiornare dati, scansionare minacce, indicizzare contenuti. Molti di questi sono configurati per girare "ogni 5 minuti" o "ogni 15 minuti" — che sembra innocuo ma, sommato, significa attività di background continua per tutta la giornata.
Soluzione: audita i tuoi cron attivi con wp cron event list --allow-root e valuta se ognuno è necessario con quella frequenza.
Trappola 2: backup che bloccano il database
Plugin di backup come UpdraftPlus o BackupBuddy spesso eseguono dump del database via PHP. Su database grossi (>500 MB) il dump può durare 5-15 minuti e tenere lock su tabelle critiche per l'intera durata.
Soluzione: usa mysqldump via cron di sistema con parametri --single-transaction --quick per minimizzare i lock, oppure sposta il backup su uno strumento esterno (Kinsta backup, BlogVault) che lavora a livello di filesystem snapshot senza lock applicativi.
Trappola 3: AI scan di sicurezza in tempo reale
I plugin di sicurezza moderni (Wordfence, MalCare, Solid Security) hanno introdotto scan AI-assisted in tempo reale nel 2025-2026. Questi scan analizzano i file del tema e dei plugin ad ogni modifica — utile per la sicurezza, ma ogni scan attiva PHP execution e I/O disco.
Soluzione: configura lo scan AI come evento schedulato (settimanale), non come scan continuo. La sicurezza migliora quando l'analisi è completa e ragionata, non quando frammenta la CPU in mini-scan continui.
Come questo si collega agli articoli precedenti della serie
Il framework background activity budget è complementare a tre articoli della serie:
In WP-Cron WordPress: ottimizzare i task background in produzione abbiamo visto il setup tecnico di WP-Cron (disabilitare spawn nativo, cron di sistema, WP-CLI). Questo articolo aggiunge il livello successivo: una volta che i cron funzionano, come farli coesistere con il traffico live.
In WordPress PHP thread 2026: come i bot AI li stanno esaurendo abbiamo visto come i bot AI saturano il pool PHP-FPM. I cron pesanti fanno la stessa cosa dall'interno: sottraggono worker al web server.
In WP-CLI 2026 guida completa AI abbiamo visto come WP-CLI può essere usato come orchestratore di operazioni complesse. La regola "esegui i cron pesanti via PHP-CLI, non via php-fpm" è il complemento operativo di quel setup.
In Toolchain agenzia WordPress moderna 2026: guida pratica completa abbiamo visto come un toolchain moderno (Bedrock + Sage + Kinsta APM + AI assistant) misura e gestisce queste metriche. Il budget monitoring è esattamente ciò che Kinsta APM fa automaticamente — e che devi replicare manualmente su stack self-hosted.
Domande frequenti
È possibile eliminare del tutto i cron WordPress?
No, non del tutto. Alcune funzionalità essenziali di WordPress (publish scheduled post, transient cleanup, WooCommerce subscription renewal) richiedono cron. Puoi spostarli da WP-Cron a cron di sistema (più affidabile, più controllabile), ma non eliminarli.
Come faccio a sapere se un cron specifico sta degradando le performance?
Il metodo più diretto è il grafico TTFB p95 diurno sovrapposto agli orari dei tuoi cron. Se vedi una "montagna" di TTFB in corrispondenza di un orario specifico ogni giorno, hai identificato il colpevole. In alternativa puoi disabilitare temporaneamente quel cron (con WP-CLI: wp cron event delete your_event) e osservare se il TTFB torna normale.
È meglio WP-Cron o cron di sistema?
Cron di sistema. WP-Cron è affidabile solo se il sito riceve traffico (perché lo spawn dei cron avviene on-request). Se il sito è a basso traffico, WP-Cron può saltare eventi per ore. Cron di sistema + wp cron event run è la configurazione professionale raccomandata.
I plugin di cache aiutano anche per i cron?
Sì, in modo indiretto. Se il sito live è servito da cache page (Cloudflare, Varnish, LiteSpeed Cache), i PHP-FPM worker non vengono occupati dal traffico normale. Questo libera capacità per i cron. Ma il problema dei cron pesanti resta: anche con cache piena, il cron in background usa risorse.
Quando serve un hosting dedicato per i cron pesanti?
Quando il volume degli import/sync supera la capacità del tuo attuale server di gestirli nelle finestre a basso traffico senza degradare il live. Su WooCommerce, tipicamente sopra i 50.000 ordini/giorno o sopra i 100.000 SKU. In quei casi conviene separare il sito "front-end" (ottimizzato per velocità) dal sistema di import (ottimizzato per throughput batch).
Lo scan AI di Wordfence rallenta davvero il sito?
Dipende dalla configurazione. Con scan continuo su modifiche frequenti, sì. Con scan schedulato settimanale, l'impatto è trascurabile (un'ora di I/O alto a settimana, di solito in finestra a basso traffico). Raccomandazione: scan schedulato, non continuo.
Checklist operativa per i prossimi 14 giorni
- Lista completa dei cron attivi (
wp cron event list) e frequenza di ognuno - Identifica i 3 cron più pesanti (per durata media e scritture DB)
- Misura TTFB p95 baseline durante i cron con i 5 strumenti sopra
- Sposta i cron pesanti in finestre a basso traffico (02:00-05:00)
- Riduci batch size dei cron import/export a 25-50 con pause 2-5s
- Migra cron pesanti da esecuzione php-fpm a PHP-CLI
- Configura monitoring budget (script
background-budget-watch.sh) - Aggiungi alert Slack/Telegram al superamento budget
- Audita plugin di sicurezza per scan AI continui e convertili in schedulati
- Verifica impatto post-modifiche con 7 giorni di monitoraggio
Riferimenti utili per approfondire
- Kinsta — WordPress performance during background activity - articolo originale sui task background come fonte di degrado
- Kinsta — PHP threads explained - reference tecnica PHP-FPM pool e concorrenza
- Kinsta — MySQL slow query log and performance - come diagnosticare query lente da cron
- WordPress.org — WP-Cron documentation - documentazione ufficiale su hook scheduling
- WordPress.org — wp cron command - tutti i comandi WP-CLI per ispezionare/eseguire cron
- MySQL — InnoDB Locking and Transaction Model - reference ufficiale lock contention
- Linux — iostat(1) man page - documentazione ufficiale iostat
- WP-CLI — cron event command - gestione eventi WP-Cron da CLI
- WP-Cron WordPress: ottimizzare i task background in produzione - guida mrtux.it al setup corretto
- WordPress PHP thread 2026: come i bot AI li stanno esaurendo - capacity planning PHP-FPM sotto carico
- WP-CLI 2026 guida completa AI - uso di WP-CLI come orchestratore
- Toolchain agenzia WordPress moderna 2026: guida pratica completa - toolchain completo agenzia moderna




Lascia un commento