Preparare un’applicazione PHP ai picchi di traffico non significa moltiplicare il numero abituale di visite per un fattore arbitrario. La capacità necessaria dipende da quante richieste si sovrappongono, da quanto dura ciascuna e dal lavoro che comporta: una pagina in cache e un’operazione che interroga diversi servizi esterni non consumano le stesse risorse.
L’obiettivo operativo è capire quale componente limita il servizio sotto un carico rappresentativo, quanto margine è disponibile e cosa fare quando si esaurisce. I test forniscono elementi concreti su cui basare le decisioni, ma non garantiscono una capacità valida in ogni situazione, perché il risultato dipende dal codice, dall’infrastruttura, dai dati e dal modello di utilizzo effettivo.
Stima il carico in base alla concorrenza e al tipo di operazione

Il volume giornaliero o mensile non è sufficiente per dimensionare le risorse. Un’applicazione può ricevere molte visite distribuite nell’arco di ore e funzionare senza problemi, oppure concentrare le richieste in pochi minuti e saturarsi. Per stimare la pressione, osserva il tasso di arrivo, la durata delle richieste e la quota di operazioni concorrenti.
In linea generale, se la durata aumenta mentre il tasso di arrivo resta invariato, più richieste rimangono attive contemporaneamente. Per questo una dipendenza lenta può aumentare la concorrenza anche se il traffico in entrata non cambia. Inoltre, il traffico può essere disomogeneo: una campagna può far aumentare bruscamente le pagine dei prodotti e le ricerche, mentre la chiusura di un periodo può concentrare autenticazioni, esportazioni o scritture.
Inizia individuando le route e le operazioni che incidono sugli obiettivi aziendali. Includi, per esempio, la navigazione pubblica, la ricerca, l’accesso, la creazione di ordini e le operazioni amministrative rilevanti. Distingui le letture dalle scritture, le richieste memorizzabili in cache da quelle che non lo sono e le richieste sincrone dai processi che potrebbero essere elaborati in una coda. Non usare la media globale per nascondere una route lenta o critica.
Costruisci un test rappresentativo e sicuro
Definisci uno o più scenari sulla base della telemetria disponibile, dei log di accesso e del calendario degli eventi noti. Documenta quale quota di richieste corrisponde a ciascuna operazione, come varia il tasso di arrivo e quanto dura ogni fase. È opportuno testare sia un carico sostenuto sia un aumento rapido, perché rivelano comportamenti diversi: l’esaurimento progressivo delle risorse rispetto a una reazione brusca a un picco.
Il test deve essere eseguito in un ambiente che rappresenti la configurazione di produzione in misura sufficiente a rendere utili i risultati. Verifica le differenze nel numero di processi, nei limiti di connessione, nelle cache, nelle dimensioni dei dati e nelle dipendenze. Se un test viene eseguito su una macchina isolata con tabelle di piccole dimensioni, non dimostra come risponderà la produzione. Evita di generare carico sugli utenti reali senza un piano e un’autorizzazione espliciti.
Proteggi i dati fin dalla progettazione dello scenario. Usa dati sintetici o anonimizzati, credenziali dedicate e permessi minimi; non copiare dati personali negli strumenti di load testing senza una base giuridica e controlli adeguati. Evita che i test inviino email, addebitino pagamenti o creino effetti irreversibili. Per le operazioni esterne, usa ambienti di test o sostituti controllati, tenendo presente che un sostituto non riproduce necessariamente la latenza né i limiti del servizio reale.
Misura latenza, errori e saturazione contemporaneamente
Registra la latenza per route e osserva i percentili, come p50, p95 e p99. La media può rimanere stabile mentre una parte delle richieste diventa molto lenta; i percentili mostrano meglio questa coda. Misura anche il tasso di errore, i timeout e il numero di richieste completate nell’unità di tempo. Un test che genera molte richieste ma anche molti errori non dimostra una capacità effettivamente utilizzabile.
Metti queste misure in relazione con le risorse e le code. In PHP, osserva l’occupazione e la coda dei processi che gestiscono le richieste, oltre a CPU, memoria e riavvii. Se usi PHP-FPM, verifica la configurazione e le metriche dei suoi processi e del web server; il nome dell’indicatore disponibile dipende dalla strumentazione. Nel database, misura le connessioni attive, l’attesa per ottenere una connessione, le query lente, i lock e l’utilizzo di CPU o disco. Osserva anche le cache, le code e le dipendenze esterne.
Stabilisci soglie legate all’esperienza e alle operazioni, non soltanto all’utilizzo della CPU. Per esempio, una route di acquisto può richiedere una latenza e un tasso di errore massimi concordati, mentre un’esportazione non critica può tollerare l’attesa o l’elaborazione asincrona. Verifica che gli orologi e le finestre di osservazione siano confrontabili e che sia possibile associare un aumento della latenza al componente che si è saturato.
Individua il primo collo di bottiglia prima di aumentare le risorse
Cerca il primo segnale che peggiora all’aumentare graduale del carico. Se la coda dei processi web cresce e la CPU di PHP rimane molto utilizzata, potrebbe esserci un lavoro costoso per richiesta o potrebbero non essere disponibili abbastanza processi. Se i processi sono in attesa di connessioni ma il database ha ancora capacità, verifica il limite del pool o la configurazione delle connessioni. Se il database mostra query lente, lock o saturazione, aggiungere processi PHP può aumentare la pressione e peggiorare il problema.
Anche le dipendenze esterne possono trattenere i processi. Verifica i tempi di connessione e risposta, i rate limit e il comportamento in caso di errore. Un timeout troppo lungo mantiene occupate le risorse; ritentare senza limiti può moltiplicare il carico. Definisci timeout limitati e una policy di retry selettiva, con attesa progressiva quando opportuno, ed evita di ripetere automaticamente operazioni non idempotenti senza protezioni.
Distingui la mancanza di capacità dall’inefficienza. Una query che esamina troppe righe, chiamate ripetute allo stesso servizio o calcoli ridondanti resteranno costosi anche aggiungendo server. Esegui il profiling di route rappresentative e riduci il lavoro per richiesta: ottimizza query e indici sulla base di dati concreti, limita i risultati, elimina le chiamate non necessarie e sfrutta la cache quando la coerenza e la privacy lo consentono. Poi ripeti il test per verificare che il miglioramento regga sotto carico.
Intervieni in ordine e pianifica una degradazione controllata
Per prima cosa riduci il costo del lavoro per richiesta e correggi le query o le dipendenze che costituiscono il limite. Poi verifica i limiti di concorrenza, i processi web e i pool di connessioni. Aumentare il numero di processi può migliorare il parallelismo finché CPU, memoria o database non si saturano; configurare più connessioni di quante il database possa gestire sposta soltanto la coda. Modifica una variabile alla volta e misura di nuovo.
Lo scaling verticale — più risorse su una singola istanza — può essere un intervento semplice se il componente può crescere e non esiste un limite strutturale. Lo scaling orizzontale — più istanze — richiede che deployment, sessioni, file, processi e database supportino questa distribuzione. Verifica il bilanciamento del carico, lo storage condiviso o esterno quando necessario, lo stato di salute delle istanze e i limiti condivisi, come le connessioni al database. Nessuna delle due opzioni corregge da sola una query inefficiente.
Definisci cosa preservare quando la capacità scarseggia. Assegna la priorità all’autenticazione, alle operazioni essenziali o alle conferme delle transazioni in base al prodotto; rimanda i report, limita le ricerche costose o disattiva temporaneamente le funzioni non essenziali. Usa le code per il lavoro che può essere completato in un secondo momento e comunica lo stato all’utente. Applica in modo esplicito rate limit o risposte di sovraccarico, con meccanismi di retry prudenti. Una degradazione controllata deve evitare di perdere operazioni confermate e offrire un’alternativa comprensibile, non restituire un falso esito positivo.
Per trasformare i test in una decisione operativa, conserva un registro con lo scenario, la configurazione, i risultati per route, il primo limite osservato, le modifiche apportate e i criteri di accettazione. Ripeti il test dopo aver modificato codice, infrastruttura, dati o dipendenze rilevanti. Prima di un picco previsto, verifica gli alert, la capacità disponibile, le procedure di rollback e i responsabili delle decisioni.
Lista di controllo prima di un picco

- Scenario: riflette route, proporzioni, ritmo e durata plausibili; include un aumento rapido e un carico sostenuto.
- Sicurezza: usa dati e credenziali adeguati, evita effetti reali indesiderati e controlla la destinazione del test.
- Osservabilità: correla latenza p95/p99, errori e throughput con processi PHP, database, cache e dipendenze.
- Diagnosi: individua il primo limite e conferma se è dovuto a saturazione, query, concorrenza o attese esterne.
- Modifica: intervieni su una causa alla volta, confronta i risultati e verifica che la saturazione non si sposti su un altro livello.
- Resilienza: definisci limiti, priorità, degradazioni, comunicazione e ripristino senza perdere operazioni confermate.
- Ripetizione: stabilisci criteri di accettazione e ripeti il test dopo modifiche importanti e prima degli eventi prevedibili.
Dimensionare con rigore significa conoscere la risposta dell’applicazione a scenari specifici e decidere mantenendo un margine, non inseguire una cifra astratta di utenti. Le misurazioni mostrano dove investire: ottimizzazione, regolazione della concorrenza, capacità aggiuntiva o una policy di degradazione che mantenga utili le funzioni essenziali.



