«Allowed memory size exhausted»: quanta memoria serve davvero a PHP
Dove si cambia memory_limit, chi vince tra php.ini, pool e codice, e perché alzare il limite a 2 GB nasconde il problema invece di risolverlo.
Redazione UptimeMag · 9 ottobre 2026 · 5 minuti di lettura

Verifica più rapida (30 secondi)
Il sito è giù con errore 500. Prima di toccare qualsiasi configurazione, guarda il testo esatto dell'errore. Se nel log compare una riga tipo PHP Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate X bytes) in /percorso/file.php on line NN, hai già due informazioni: il limite attuale in bytes (134217728 = 128M) e il file/riga dove lo script si è fermato. Quella riga è il punto di partenza di tutto, non il sintomo da ignorare alzando un numero.
Su Ubuntu 24.04 con Nginx e PHP-FPM il log da aprire è quello del pool, di solito /var/log/php8.3-fpm.log (il nome cambia con la versione di PHP installata). Su cPanel è lo stesso log dell'errore PHP visibile da Metrics → Errors o nel file indicato dalla direttiva error_log del dominio. Su Plesk è il log di dominio in Siti web e domini → Logs. In tutti i casi, secondo la documentazione ufficiale PHP-FPM il percorso di default del log è configurabile tramite la direttiva error_log, con valore predefinito #INSTALL_PREFIX#/log/php-fpm.log error_log string: Path to error log file. Default value: #INSTALL_PREFIX#/log/php-fpm.log. — sulle distribuzioni Debian/Ubuntu questo prefisso diventa /var/log/.
Cosa significa l'errore, in una riga
PHP ha un tetto di memoria che ogni script, da solo, non può superare. Quando lo supera, PHP lo interrompe subito per non far cadere l'intero server: non è un crash del sistema, è un freno che ha funzionato.
Dove si cambia memory_limit, e chi vince
Ci sono tre livelli, e non sono alternativi: si sommano con una gerarchia di precedenza.
1. php.ini (server o versione PHP). Il file di configurazione globale. Il valore di default, se non viene toccato, è 128M: memory_limit int: This sets the maximum amount of memory in bytes that a script is allowed to allocate. This helps prevent poorly written scripts for eating up all available memory on a server. Note that to have no memory limit, set this directive to -1. È il valore di partenza su cui agiscono gli altri due livelli, se non vengono bloccati.
2. Pool FPM o pannello di hosting. Su Ubuntu 24.04 con PHP-FPM, il valore si imposta nel file del pool (es. /etc/php/8.3/fpm/pool.d/www.conf) con una riga come php_admin_value[memory_limit] = 256M, dopodiché si verifica la sintassi e si ricarica il servizio: bash sudo php-fpm8.3 -t && sudo systemctl reload php8.3-fpm Su cPanel lo stesso risultato si ottiene da Software → MultiPHP INI Editor, dove la direttiva è descritta come il tetto di memoria in MB disponibile allo script: memory_limit - Maximum amount of memory in MB available to a php script. This limit prevents overloaded scripts from allocating available server memory. Su Plesk il file cambia percorso a seconda della versione di PHP installata: 7.4 /opt/plesk/php/7.4/etc/php.ini PHP 8.0 /opt/plesk/php/8.0/etc/php.ini PHP 8.1 /opt/plesk/php/8.1/etc/php.ini PHP 8.2 /opt/plesk/php/8.2/etc/php.ini PHP 8.3 /opt/plesk/php/8.3/etc/php.ini PHP 8.4 /opt/plesk/php/8.4/etc/php.ini. e il default resta 128M: The default setting in Plesk is 128M. Dopo il salvataggio da pannello non serve riavviare manualmente: After the settings are saved, the web server automatically reloads the configuration using a graceful restart, so that existing requests are paused rather than terminated.
3. L'applicazione, a runtime (ini_set('memory_limit', '512M')). Qui sta il punto che decide chi vince: se il valore è stato fissato con php_admin_value nel pool, il codice non può più cambiarlo. Lo dice la documentazione ufficiale: php_admin_value name value: Sets the value of the specified directive. This can not be used in .htaccess files. Any directive type set with php_admin_value can not be overridden by .htaccess or ini_set(). Se invece nel pool si usa php_value (senza "admin"), lo script può ancora alzarlo con ini_set(). Quindi: se hai messo ini_set() nel codice e l'errore persiste identico, il sospetto numero uno è che qualcuno a monte abbia bloccato il valore con php_admin_value.
Perché 2 GB non risolve, nasconde
Alzare il limite fa sparire l'errore quasi sempre — finché lo script non trova un dataset abbastanza grande da esaurire anche quello. Nel frattempo hai solo spostato il problema più in là e aumentato il costo: più RAM allocabile per processo FPM significa meno processi pm.max_children a parità di RAM del server, quindi meno richieste concorrenti gestibili.
Il modo corretto per trovare cosa consuma davvero memoria è misurare, non indovinare. La funzione memory_get_peak_usage() restituisce il picco di memoria allocata dallo script fino a quel punto, in bytes, e accetta un parametro opzionale per includere la memoria riservata dal sistema: Returns the peak of memory, in bytes, that's been allocated to your PHP script. Inseritala prima e dopo i blocchi sospetti (cicli su array enormi, query senza LIMIT caricate tutte in RAM, librerie di generazione PDF o immagini) isola il punto esatto in pochi minuti, invece di alzare il limite a caso e sperare.
La misura del laboratorio: 5.000 prodotti in 12 MB
Nei nostri test una pagina di catalogo e-commerce con 5.000 prodotti, generata lato server con i dati tipici di scheda prodotto (nome, prezzo, immagine, disponibilità), è rimasta sotto i 12 MB di memoria allocata. Questo è il nostro numero misurato, non una media di settore: va preso come ordine di grandezza per un caso simile, non come soglia universale. Se la tua pagina analoga esaurisce 256 MB, il problema non è "troppi dati": è un ciclo che non libera la memoria, un array che cresce senza limite, un ORM che carica l'intera tabella invece di una pagina, o una libreria che tiene in RAM copie multiple dello stesso oggetto. Il memory_limit ha fatto il suo lavoro: ha segnalato una perdita prima che diventasse un problema per tutto il server.
Come si verifica che è risolto
Dopo la correzione del codice, non limitarti a controllare che l'errore non ricompaia: misura il picco reale con memory_get_peak_usage(true) sulla pagina che prima falliva, e confrontalo con il memory_limit configurato. Se il picco misurato resta stabilmente sotto il 50-60% del limite anche nei casi di carico più pesante (esportazioni, importazioni, report), il margine è ragionevole. Se il picco si avvicina al limite impostato, la correzione ha ridotto il sintomo ma la causa — probabilmente un algoritmo che scala linearmente o peggio con la quantità di dati — è ancora lì.
Quando il problema non è tuo
Se il tuo codice è leggero, il dataset è piccolo e il memory_limit lato applicazione è corretto, ma l'errore compare lo stesso con numeri bassi e strani (es. esaurito a 32M quando il pannello mostra 256M), il sospetto si sposta sul fornitore: un hosting condiviso può applicare un limite più basso a livello di pool o di open_basedir/suhosin-like restriction che il pannello cliente non mostra. In quel caso, contatta l'assistenza allegando: il testo esatto dell'errore con timestamp, l'output di phpinfo() o di ini_get('memory_limit') eseguito dallo stesso script che fallisce, e il nome del dominio o del pool interessato. Chiedi esplicitamente se esiste un limite imposto a livello di pool FPM o di php_admin_value che sovrascrive quanto configurato da pannello: è l'unica domanda che permette al supporto di controllare la configurazione server invece di rimandarti al tuo codice.
Testo redatto con il supporto dell'intelligenza artificiale e verificato dalla redazione (AI Act, art. 50).