I limiti dell’hosting condiviso compaiono raramente nella pagina dei piani: «illimitato» di solito riguarda il traffico, i siti o le caselle email, non le risorse del server, e le pagine di supporto dei grandi provider indicano un limite di file (inode), un numero di processi PHP simultanei, una quota di CPU, memoria, connessioni al database ed email all’ora. I limiti che un sito raggiunge per primi sono di solito i processi PHP simultanei e la CPU: i visitatori vedono un caricamento lento, poi un errore 503, 504 o 508 «Resource Limit Is Reached». Qui sotto trovi i limiti pubblicati da cinque provider noti, un test sul nostro banco di prova e uno script che mostra i tuoi limiti direttamente da PHP.
Come abbiamo verificato
Il 10 novembre 2026 abbiamo letto le pagine sui limiti e le policy pubblicate da Hostinger, Bluehost, SiteGround, Namecheap e HostGator (link nella tabella). Lo stesso giorno, su un banco di prova (container Ubuntu 24.04.5, 2 vCPU, nginx 1.24.0, PHP-FPM 8.3.6, MariaDB 10.11.14), abbiamo riprodotto limiti tipici: un pool PHP-FPM con pm.max_children = 4, timeout, limiti di upload, MAX_USER_CONNECTIONS 3 per l’utente del database e tetti di CPU e memoria tramite cgroups, lo stesso meccanismo del kernel su cui si basano i limiti LVE di CloudLinux (CloudLinux in sé non è stato eseguito sul banco). Sono risultati del banco di prova, non dati dei server RichHost.
Cosa dicono davvero le condizioni dei piani «illimitati»
«Illimitato» indica ciò che il provider non misura: il traffico, il numero di domini, a volte lo spazio su disco. Le risorse tecniche sono sempre limitate, perché centinaia di account condividono lo stesso server; l’unica differenza è se il provider pubblica i numeri. Ecco cosa dicono le pagine di supporto ufficiali:
| Provider, piani | File (inode) | Processi PHP simultanei | CPU | Email dal server | Database |
|---|---|---|---|---|---|
| Hostinger: Single / Premium / Business (venduto come Unlimited) | 200.000 / 400.000 / 600.000 | 20 / 40 / 60 PHP worker | 1 / 1 / 2 core | 10 al minuto, fino a 100 al giorno | 3 GB; 25 / 50 / 75 connessioni; query fino a 60 / 60 / 120 s |
| Bluehost: condiviso | massimo 200.000, soglia indicativa 50.000 | non pubblicato | limitata, senza numeri | da 200 all’ora (fino a 1.000 nei livelli superiori) | 5 GB per database, 10 GB in totale |
| SiteGround: StartUp / GrowBig / GoGeek | 200.000 / 400.000 / 600.000 | non pubblicato | 1.000 / 2.000 / 4.000 secondi di CPU all’ora | non pubblicato | fino a 1.000 MB per database |
| Namecheap: Stellar / Stellar Plus / Stellar Business | 300.000 / 300.000 / 600.000 | 20 / 30 / 40 entry process | 50 / 50 / 100% di un core | 50 / 200 / 10.000 all’ora per dominio | non pubblicato |
| HostGator: condiviso | 1.000.000 di file | 25 processi simultanei | 25% della CPU | 500 all’ora | 5 GB; 25 connessioni |
Dettagli facili da non notare. La pagina di Bluehost sugli inode precisa che oltre 200.000 file un account rientra nella sezione della sua policy sull’uso eccessivo delle risorse e che oltre 1.000.000 è possibile la sospensione. Namecheap esclude dai backup automatici gli account con più di 200.000 inode (tranne Stellar Business). SiteGround consiglia di eseguire lo stesso cron job non più spesso di ogni 30 minuti e limita ogni processo a 768 MB di memoria. Hostinger indica inoltre un max_execution_time PHP di 360 s e un tempo massimo per le query al database. L’ex A2 Hosting (oggi hosting.com) non promette più «illimitato» nella pagina dei piani e lì non pubblica alcun numero sui limiti.
CloudLinux, che gira su gran parte dei server di hosting condiviso, usa questi valori predefiniti secondo la documentazione di CloudLinux: un core di CPU (SPEED 100%), 1024 MB di memoria fisica (PMEM), 20 entry process (EP), 100 processi in totale (NPROC), 1024 KB/s di I/O su disco. Ogni provider può modificarli tutti.
Quali limiti scattano per primi e come si manifestano
Alcuni limiti danno subito un errore, altri rallentano soltanto il sito, altri ancora rompono una funzione senza mostrare alcun errore a schermo. La tabella unisce i nostri test con la documentazione di CloudLinux:
| Limite | Cosa vede il visitatore | Dove trovare la traccia |
|---|---|---|
| Processi PHP simultanei (EP, PHP worker, pm.max_children) | Una coda, poi 504; su CloudLinux 508 Resource Limit Is Reached | Grafico degli entry process nel pannello; riga «server reached max_children setting» nel log di PHP-FPM |
| CPU (SPEED, secondi di CPU) | Il sito è semplicemente più lento, nessun errore | Grafico CPU nel pannello, tempo di risposta in crescita |
| Memoria dell’account (PMEM) | 500, 502 o 503, niente nel log di PHP | Processo terminato con SIGKILL, grafico della memoria |
| memory_limit di PHP | 500 o la pagina WordPress di «errore critico» | error_log: Allowed memory size exhausted |
| max_execution_time | 500 dopo qualche secondo di lavoro | error_log: Maximum execution time exceeded |
| Timeout del proxy o di PHP-FPM | 504 Gateway Time-out o 502 Bad Gateway | error.log del web server |
| upload_max_filesize, post_max_size | La pagina risponde 200 ma il file manca; oppure 413 | Codice di errore 1 in $_FILES, avviso su POST Content-Length |
| Inode | Non si possono creare nuovi file: cache, sessioni, miniature, posta | No space left on device anche se il disco ha spazio libero |
| MySQL max_user_connections | Error establishing a database connection | ERROR 1226 nel log |
Approfondimenti sui singoli casi: l’errore 508 Resource Limit Is Reached, come aumentare memory_limit e il limite di inode nell’hosting.
Test: cosa riceve il quinto visitatore quando ci sono quattro processi PHP
Abbiamo configurato un pool PHP-FPM con quattro processi e una pagina che attende 5 secondi, come una pagina che aspetta una API esterna lenta o una query pesante al database. Poi abbiamo inviato richieste in contemporanea:
- 5 richieste: le prime quattro hanno risposto in 5,0 s, la quinta in 9,8 s. Nessun errore: la richiesta ha semplicemente atteso in coda un processo libero. Nel log di PHP-FPM è comparsa la riga
server reached max_children setting (4), consider raising it. - 12 richieste con timeout del proxy di 10 s: le richieste da 1 a 4 hanno ricevuto 200 in 5,0 s, quelle da 5 a 8 hanno ricevuto 200 in 9,8 s, quelle da 9 a 12 hanno ricevuto 504 Gateway Time-out dopo esattamente 10 s.
- Fantasmi dopo un 504: subito dopo quella raffica abbiamo aperto la pagina più leggera. Ha impiegato 3,75 s invece di rispondere all’istante, perché tutti e quattro i processi stavano ancora eseguendo le richieste i cui visitatori avevano già ricevuto un 504.
La lezione: il limite di concorrenza non riguarda il numero di visitatori, ma il numero di richieste lente. Quattro processi servono decine di persone se una pagina viene generata in 0,1 s, e si bloccano al quinto visitatore se ogni pagina aspetta 5 secondi un servizio esterno. Su CloudLinux un visitatore che raggiunge il limite EP riceve subito un 508, senza coda. Come trovare in sicurezza il tuo tetto lo spiega la nostra guida al test di carico di un sito web.
CPU: non un errore, ma un rallentamento
Abbiamo eseguito la stessa pagina, con una quantità fissa di calcolo, sotto un tetto di CPU impostato con cgroup. Tutte le 120 richieste hanno restituito 200; è cambiato solo il tempo:

Quattro richieste simultanee si dividono una sola quota, quindi al 25% di un core una pagina che senza tetto rispondeva in 0,35 s ha impiegato in media 3,83 s. Ecco che aspetto ha «il sito è lento, ma il pannello dice che va tutto bene».
Timeout: tre orologi diversi
max_execution_timesu Linux conta il tempo di CPU dello script. Un ciclo di calcolo con un limite di 3 s è terminato con un 500 eMaximum execution time of 3 seconds exceeded, mentre una pagina che ha atteso 6 s (sleep) con lo stesso limite ha restituito 200. L’attesa di una API o del database non viene conteggiata.request_terminate_timeoutin PHP-FPM conta il tempo reale trascorso: sia il calcolo sia l’attesa sono stati interrotti dopo 20 s e il visitatore ha ricevuto 502.- Il timeout del proxy (
fastcgi_read_timeoutin nginx) ha restituito 504 dopo 10 s, anche se PHP continuava a lavorare.
Memoria, upload e database
- Allocare 200 MB con
memory_limit = 128Mha prodotto un 500 e una riga nel log di PHP. Quando abbiamo limitato la memoria dell’intero pool a 256 MB (come PMEM in LVE) e alzato memory_limit a 1024M, il kernel ha terminato il processo: 502 e nemmeno una riga nel log di PHP. - Un file da 3 MB con
upload_max_filesize = 2M: la pagina ha restituito 200 ma il file non è mai arrivato (codice di errore 1). Un file da 9 MB conpost_max_size = 8M: è sparito l’intero modulo, campi di testo compresi. Lo stesso file da 3 MB tramite nginx con le impostazioni predefinite: 413 Request Entity Too Large. - Un utente del database con
MAX_USER_CONNECTIONS 3: su cinque richieste simultanee, due hanno ricevutoERROR 1226 ... has exceeded the 'max_user_connections' resourcein 0,002 s. In questo caso WordPress mostra «Error establishing a database connection». Un limite sulla durata delle query (max_statement_time = 2) ha interrotto una query pesante dopo esattamente 2 s con ERROR 1969.
Come verificare i tuoi limiti: lo script limits.php
Il pannello dell’hosting non mostra tutto. Abbiamo testato lo script qui sotto sul banco in due modalità: un pool normale e un pool con le funzioni shell disattivate e open_basedir attivo, come su molti hosting condivisi. Mostra i valori PHP effettivi, l’upload più grande possibile, la quota di CPU che lo script ottiene davvero in 1 secondo, i limiti dei processi da /proc e cgroup (se leggibili), ulimit -a (se la shell è consentita), il numero di file nella tua home e i limiti del database, compreso MAX_USER_CONNECTIONS da GRANT.
- Sostituisci
KEYcon una tua stringa lunga. - Carica il file nella root del sito accanto a wp-config.php (per un altro CMS compila l’array
$db). - Apri
https://your-site/limits.php?key=YOUR_KEY. Senza la chiave lo script restituisce 404. - Salva l’output e cancella subito il file.
<?php
// limits.php: shows the limits that really apply to this hosting account.
// 1) set your own KEY, 2) upload next to wp-config.php (or fill DB_* below),
// 3) open https://your-site/limits.php?key=YOUR_KEY, 4) DELETE the file afterwards.
const KEY = 'change-me';
$db = ['host' => '', 'user' => '', 'pass' => '', 'name' => '']; // empty = read wp-config.php
if (KEY === 'change-me' || !hash_equals(KEY, (string)($_GET['key'] ?? ''))) { http_response_code(404); exit; }
header('Content-Type: text/plain; charset=utf-8');
function row($k, $v) { printf("%-28s %s\n", $k, is_bool($v) ? ($v ? 'yes' : 'no') : $v); }
function head($t) { echo "\n== $t\n"; }
function bytes($v) { $n = (float)$v; $u = strtolower(substr(trim($v), -1)); return $u === 'g' ? $n * 1073741824 : ($u === 'm' ? $n * 1048576 : ($u === 'k' ? $n * 1024 : $n)); }
function readable($f) { return @is_readable($f) ? trim((string)@file_get_contents($f)) : null; }
head('PHP');
row('version / SAPI', PHP_VERSION . ' / ' . PHP_SAPI);
foreach (['memory_limit', 'max_execution_time', 'max_input_time', 'upload_max_filesize', 'post_max_size',
'max_file_uploads', 'max_input_vars', 'default_socket_timeout', 'open_basedir', 'disable_functions',
'opcache.enable', 'opcache.memory_consumption', 'sendmail_path'] as $k) {
$v = ini_get($k);
row($k, $v === false ? '(not available)' : ($v === '' ? '(empty)' : $v));
}
$up = min(bytes(ini_get('upload_max_filesize')), bytes(ini_get('post_max_size')) ?: PHP_INT_MAX);
row('largest upload via PHP', round($up / 1048576, 1) . ' MB (web server may allow less)');
head('This process');
$u = function_exists('posix_getpwuid') ? (posix_getpwuid(posix_geteuid())['name'] ?? '?') : get_current_user();
row('pid / user', getmypid() . ' / ' . $u);
$t0 = microtime(true); $r0 = getrusage(); $n = 0;
while (microtime(true) - $t0 < 1.0) { $n++; } // 1 s of pure CPU work
$r1 = getrusage(); $wall = microtime(true) - $t0;
$cpu = ($r1['ru_utime.tv_sec'] + $r1['ru_utime.tv_usec'] / 1e6 + $r1['ru_stime.tv_sec'] + $r1['ru_stime.tv_usec'] / 1e6)
- ($r0['ru_utime.tv_sec'] + $r0['ru_utime.tv_usec'] / 1e6 + $r0['ru_stime.tv_sec'] + $r0['ru_stime.tv_usec'] / 1e6);
row('CPU test 1 s', sprintf('cpu %.2f s of wall %.2f s = %d%% (loops %s)', $cpu, $wall, 100 * $cpu / $wall, number_format($n)));
row('peak memory', round(memory_get_peak_usage(true) / 1048576, 1) . ' MB');
row('max RSS (getrusage)', round($r1['ru_maxrss'] / 1024, 1) . ' MB');
head('OS limits (/proc, cgroup)');
if ($l = readable('/proc/self/limits')) {
foreach (explode("\n", $l) as $line) {
if (preg_match('/^(Max cpu time|Max processes|Max open files|Max address space)\s+(\S+)\s+(\S+)/', $line, $m)) row($m[1], "soft $m[2], hard $m[3]");
}
} else { row('/proc/self/limits', 'not readable (open_basedir?)'); }
foreach (explode("\n", (string)readable('/proc/self/cgroup')) as $line) { // own cgroup (v1 and v2)
$p = explode(':', $line, 3); if (count($p) < 3) continue;
$files = $p[1] === '' ? ['memory.max', 'cpu.max', 'pids.max'] : ['memory' => ['memory.limit_in_bytes'],
'cpu' => ['cpu.cfs_quota_us', 'cpu.cfs_period_us'], 'pids' => ['pids.max']][$p[1]] ?? [];
foreach ($files as $f) {
$path = '/sys/fs/cgroup' . ($p[1] === '' ? '' : '/' . $p[1]) . rtrim($p[2], '/') . '/' . $f;
if (($v = readable($path)) !== null) row("cgroup $f", $v);
}
}
$fn = 'shell_exec';
if (function_exists($fn) && !in_array($fn, array_map('trim', explode(',', (string)ini_get('disable_functions'))), true)) {
head('ulimit -a (shell)');
echo $fn('ulimit -a 2>&1') ?: "(no output)\n";
} else { row('shell_exec', 'disabled'); }
head('Files (inodes)');
$home = getenv('HOME') ?: dirname(__DIR__);
$base = @is_readable($home) ? $home : __DIR__;
$cnt = 0; $stop = microtime(true) + 15;
try {
$it = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($base, FilesystemIterator::SKIP_DOTS),
RecursiveIteratorIterator::SELF_FIRST, RecursiveIteratorIterator::CATCH_GET_CHILD);
foreach ($it as $x) { $cnt++; if (microtime(true) > $stop) { $cnt .= '+ (stopped after 15 s)'; break; } }
} catch (Throwable $e) { $cnt .= ' (error: ' . $e->getMessage() . ')'; }
row('files+dirs under', "$base: $cnt");
row('disk free (volume)', round(@disk_free_space(__DIR__) / 1073741824, 1) . ' GB (volume, not your quota)');
head('Database');
if ($db['user'] === '' && is_readable(__DIR__ . '/wp-config.php')) {
$c = file_get_contents(__DIR__ . '/wp-config.php');
foreach (['host' => 'DB_HOST', 'user' => 'DB_USER', 'pass' => 'DB_PASSWORD', 'name' => 'DB_NAME'] as $k => $c2)
if (preg_match("/define\(\s*['\"]{$c2}['\"]\s*,\s*['\"](.*?)['\"]\s*\)/", $c, $m)) $db[$k] = $m[1];
}
if ($db['user'] === '' || !class_exists('mysqli')) { row('database', 'no credentials or no mysqli'); exit; }
mysqli_report(MYSQLI_REPORT_OFF);
$h = $db['host'] ?: 'localhost'; $port = null; $sock = null;
if (strpos($h, ':') !== false) { [$h, $p] = explode(':', $h, 2); is_numeric($p) ? $port = (int)$p : $sock = $p; }
$m = @new mysqli($h, $db['user'], $db['pass'], $db['name'], $port, $sock);
if ($m->connect_errno) { row('connect error', $m->connect_errno . ' ' . $m->connect_error); exit; }
$q = $m->query('SELECT VERSION() v, @@max_connections mc, @@max_user_connections muc, @@wait_timeout wt, @@max_allowed_packet map');
foreach ($q->fetch_assoc() as $k => $v) row(['v' => 'server version', 'mc' => 'max_connections (server)',
'muc' => 'max_user_connections', 'wt' => 'wait_timeout', 'map' => 'max_allowed_packet'][$k], $v);
foreach (['@@max_statement_time' => 'max_statement_time (MariaDB)', '@@max_execution_time' => 'max_execution_time (MySQL, ms)'] as $var => $label)
if ($r = $m->query("SELECT $var")) row($label, $r->fetch_row()[0]);
if ($r = $m->query('SHOW GRANTS FOR CURRENT_USER()')) {
while ($g = $r->fetch_row()) if (preg_match('/WITH (.*)$/', $g[0], $mm)) row('per-user limits (GRANT)', $mm[1]);
}
if ($r = $m->query('SELECT COALESCE(ROUND(SUM(data_length+index_length)/1048576,1),0) FROM information_schema.tables WHERE table_schema = DATABASE()'))
row('this database size', $r->fetch_row()[0] . ' MB');
echo "\nDone. Delete this file now.\n";
Sul banco con un tetto di CPU del 25% la riga del test diceva CPU test 1 s cpu 0.27 s of wall 1.04 s = 26%, e più in basso lo script mostrava la quota stessa: cgroup cpu.cfs_quota_us 25000. Senza quota ma su una macchina carica il test ha mostrato il 70%: una percentuale bassa può dipendere anche dai vicini, quindi leggi le due righe insieme. Sui server CloudLinux i file di cgroup di solito non sono leggibili da un account; in quel caso affidati al test della CPU e ai grafici del pannello. Per verificare o cambiare PHP, consulta la nostra guida sulla versione di PHP sull’hosting.
Due cose che lo script non può mostrare: il limite orario di email (lo conosce solo il server di posta del provider) e l’intervallo minimo dei cron. Chiedi entrambe al supporto; la configurazione delle attività è spiegata nella nostra guida ai cron job sull’hosting.
Se succede X, fai Y
| Se | Fai |
|---|---|
| 508 o 503 occasionali, e il log cita max_children o il limite EP | Trova le richieste lente (slowlog, Query Monitor) e attiva la cache delle pagine; aggiungere processi senza questo rimanda solo il problema |
| Il sito è lento senza errori e il grafico della CPU tocca il tetto | Cache delle pagine, OPcache, rimuovere i plugin pesanti; se non basta, un piano superiore |
| 504 durante import, export o backup | Esegui queste attività a blocchi tramite cron o WP-CLI, non dal browser |
| 500 e «Allowed memory size exhausted» | Alza memory_limit entro i limiti del piano e scopri cosa consuma la memoria |
| 502 o 503 senza nulla nel log di PHP | Sospetta il limite di memoria dell’account e contatta il supporto indicando l’ora esatta dell’errore |
| Un file non si carica e non c’è alcun errore | Confronta upload_max_filesize, post_max_size e il limite del web server: vince il più piccolo |
| «Error establishing a database connection» sotto carico | Controlla MAX_USER_CONNECTIONS, elimina le query lunghe e le connessioni persistenti |
| Non si possono creare nuovi file anche se c’è spazio su disco | Conta gli inode, pulisci cache, sessioni e vecchi backup |
Come funziona su RichHost
I piani di hosting RichHost includono traffico illimitato e un numero illimitato di siti, caselle email e account FTP su dischi NVMe. La posta parte da indirizzi IP puliti, il recapito è monitorato e chi invia spam viene bloccato, quindi per gli invii massivi conviene usare un servizio dedicato. Chiedi al supporto i limiti esatti di processi, memoria e file di un piano specifico: il supporto lavora dalle 10:00 alle 20:00, ora di Kyiv, e risponde in circa 30 minuti. Lo script qui sopra ti mostrerà cosa si applica davvero al tuo account.
Domande frequenti
Che differenza c’è tra 503, 504 e 508?
Su CloudLinux, 508 significa che l’account ha esaurito i processi simultanei. 503 dipende più spesso dalla memoria o dal numero di processi. 504 significa che il proxy non ha ricevuto in tempo una risposta da PHP.
Posso alzare i limiti senza cambiare piano?
I valori PHP (memory_limit, max_execution_time, dimensione degli upload) spesso si possono modificare nel pannello entro i limiti del piano. CPU, memoria dell’account e limiti dei processi li stabilisce il provider e cambiano solo con un altro piano.
È sicuro lasciare limits.php sul sito?
No. Rivela impostazioni del server e del database. Eseguilo con la tua chiave, salva l’output e cancella il file.



