---
title: "Performance PHP su Hetzner, OVH e Digital Ocean: come ho ridotto un checkout da 4,2 secondi a 280 millisecondi senza upgrade hardware"
description: "Performance PHP su Hetzner, OVH e Digital Ocean: profiling, fix N+1, indici, OPcache, Redis e code asincrone. Da 4,2s a 280ms senza nuovo hardware."
canonical: "https://www.mauriziofonte.it/blog/post/ottimizzazione-performance-php-server-hetzner-ovh-digital-ocean.html"
author: "Maurizio Fonte"
date: "2025-06-10T09:21:11+02:00"
modified: "2026-04-14T17:48:55+02:00"
section: "Performance"
tags: ["Performance", "Database"]
license: "Riuso e citazione consentiti con attribuzione e link alla fonte"
---

[Performance](https://www.mauriziofonte.it/blog/cat/performance.html) [Database](https://www.mauriziofonte.it/blog/cat/database.html)

# [Performance PHP su Hetzner, OVH e Digital Ocean: come ho ridotto un checkout da 4,2 secondi a 280 millisecondi senza upgrade hardware](https://www.mauriziofonte.it/blog/post/ottimizzazione-performance-php-server-hetzner-ovh-digital-ocean.html)

Martedì 10 Giugno 2025, alle 09:21 ![Performance PHP su Hetzner, OVH e Digital Ocean: come ho ridotto un checkout da 4,2 secondi a 280 millisecondi senza upgrade hardware](https://www.mauriziofonte.it/image/001720200-ottimizzazione-performance-php-server-hetzner-ovh-digital-ocean.jpg)

Il 9 gennaio 2025 mi ha contattato il proprietario di un'azienda veronese che gestisce un portale B2B di forniture per il settore HoReCa, con un fatturato di circa 6 milioni di euro l'anno e un picco stagionale concentrato nelle sei settimane prima dell'estate. Il portale girava su un server dedicato Hetzner AX52 (Ryzen 7 7700, 64 GB RAM DDR5, 2×NVMe da 1 TB in RAID 1) con stack LEMP standard - Nginx 1.24, PHP-FPM 8.2, MySQL 8.0 - e una codebase Laravel 10 che aveva otto anni di evoluzione organica sulle spalle. Il problema concreto: da metà dicembre i clienti che cercavano di completare un ordine vedevano il checkout impallarsi per 4-6 secondi, e in un certo numero di casi fallire del tutto con timeout HTTP 504 dal reverse proxy Cloudflare.

Il proprietario aveva già parlato con il suo account manager Hetzner e si stava facendo preventivare un upgrade a un AX102 (32 core, 128 GB RAM) per circa 380 euro al mese in più - quasi 4.500 euro l'anno di OPEX aggiuntivi. Quando mi ha chiesto un secondo parere al telefono, l'ho convinto a darmi otto ore di lavoro prima di firmare l'upgrade. Otto ore dopo, distribuite su due giornate lavorative, il checkout era a 280 millisecondi di mediana e 750 millisecondi al 99° percentile, con il 99,2% delle richieste sotto il secondo anche in fascia di picco. Hardware originale, zero euro di costi infrastrutturali aggiuntivi, zero modifiche alla tariffazione del provider.

Questo articolo è il distillato del metodo che applico in queste situazioni - non un elenco di "trucchi per velocizzare PHP" da blog motivazionale, ma il processo ordinato di diagnostica e remediation che ho rifinito su decine di clienti negli ultimi anni. Il principio guida che ripeto sempre ai titolari PMI è uno solo: *l'hardware è quasi sempre l'ultima leva da tirare, non la prima*. Un server più grosso ti compra qualche mese di tregua, ma il problema vero - la query inefficiente, l'indice mancante, la cache mal pianificata, il pattern N+1 dimenticato in un loop - resta lì e ti torna addosso al prossimo picco di traffico, peggio di prima e in un contesto in cui hai già speso i soldi dell'upgrade.

## Perché "ottimizzare a sentimento" è l'errore che fa raddoppiare il budget IT della tua PMI?

L'errore numero uno che vedo fare in queste situazioni è esattamente quello che chiamo "ottimizzazione a sentimento". Lo sviluppatore o l'agenzia che ha ereditato il sistema apre un editor, guarda il codice del checkout, e inizia a "ottimizzare" cose che *pensa* siano lente - sostituendo un `array_map` con un `foreach`, aggiungendo memoize manuale ai metodi, riscrivendo le query Eloquent in raw SQL "perché vanno più veloci", togliendo abstraction layer "che rallentano". Il problema di questo approccio è che senza profiling reale stai ottimizzando *le cose sbagliate*, e ogni ora spesa a riscrivere codice che non era il collo di bottiglia è un'ora in più verso il fatidico upgrade hardware che a quel punto diventa inevitabile. Nel caso del cliente veronese, il primo dev che aveva guardato il sistema era convinto che il problema fosse "il template Blade troppo nidificato". Il rendering del template Blade contribuiva per 12 millisecondi al tempo totale di 4.200 millisecondi. Zero virgola tre per cento.

La regola che applico sempre nei primi trenta minuti di un intervento di performance è una sola, e non ammette eccezioni: *prima profili con strumenti, poi parli e intervieni*. Gli strumenti principali sono tre. Per il backend PHP uso [Blackfire come profiler ufficiale di SensioLabs, documentato in dettaglio nella guida introduttiva](https://blackfire.io/docs/introduction), che ti dà una flame graph con la decomposizione esatta del tempo speso in ogni chiamata di funzione e in ogni query SQL generata dall'applicazione. Per il database attivo lo `slow_query_log` di MySQL, impostato a 100 millisecondi come soglia, in modo da catturare tutte le query oltre quella soglia per 24 ore consecutive di traffico reale. Per il frontend, quando serve, uso Lighthouse e WebPageTest. Lo slow query log si attiva con queste quattro righe in `/etc/mysql/mysql.conf.d/mysqld.cnf`:

```ini
[mysqld]
slow_query_log = 1
slow_query_log_file = /var/log/mysql/slow.log
long_query_time = 0.1
log_queries_not_using_indexes = 1
```

Sul cliente veronese, in trenta minuti di profiling Blackfire avevamo già la risposta definitiva: l'80% del tempo della richiesta veniva speso in 47 query identiche alla tabella `quote_lines` - il classico pattern N+1 generato da un `foreach` che non eager-loadava la relazione `quoteLines` sul `Quote` model. Il punto critico di questa diagnosi è che senza profiling quel pattern era *completamente invisibile* al code review tradizionale: il codice Laravel sembrava normale, un semplice loop su un model con accesso a un attributo relazionale. Ma in produzione, con dataset reali da 200-400 quote per cliente nel periodo di picco, generava una tempesta di query che il MySQL faticava a smaltire. La regola operativa che do ai team è: *qualunque ciclo che accede a un attributo relazionale di un Eloquent model è sospetto fino a prova contraria*. La prova contraria è un eager-load esplicito con `with('relazione')` o un commento in codice che spiega perché il caricamento lazy è intenzionale in quel punto specifico. Niente di meno.

## Database: dove vive l'ottanta per cento del problema in un'app PHP lenta

Una volta identificato il pattern N+1 con il profiler, il fix è quasi banale: aggiungere `with(['quoteLines.product', 'quoteLines.taxRate'])` al query builder che caricava la lista dei preventivi nella schermata di checkout. Da 47 query a 3 query in totale per la pagina. Tempo del checkout sceso istantaneamente da 4.200 ms a 1.100 ms. Ma 1.100 ms erano ancora molti, troppi per un'esperienza utente accettabile, e il profiler ora indicava la seconda voce pesante: una singola query sulla tabella `shipping_quotes` che impiegava 740 ms su un dataset di circa 1,2 milioni di record storici accumulati negli anni. Un `EXPLAIN` mi ha rivelato il problema in dieci secondi di analisi:

```sql
EXPLAIN SELECT * FROM shipping_quotes
WHERE carrier_id = 7 AND weight_band = 'L'
  AND zip_code_prefix = '371' LIMIT 1;
```

Il piano di esecuzione mostrava `type: ref`, `rows: 18432`, `key: idx_zip_code_prefix`: la query filtrava su tre colonne (`zip_code_prefix`, `weight_band`, `carrier_id`) ma esisteva solo un indice singolo su `zip_code_prefix`, e il database scansionava migliaia di righe per ogni richiesta prima di trovare il match. Il fix è stato un indice composito sui tre campi nella loro selettività decrescente (`carrier_id` ha 7 valori distinti, `weight_band` ne ha 4, `zip_code_prefix` ne ha migliaia), applicato con una semplice migration Laravel e deployato durante una finestra a basso traffico di dieci minuti. La query è scesa da 740 ms a 8 ms. Il tempo del checkout dopo questo secondo fix: 320 ms. La regola operativa che insegno ai team su questo livello è: *ogni query che appare nello slow log con frequenza superiore a 10 chiamate al minuto e tempo medio sopra i 100 ms va ispezionata con `EXPLAIN`, e ogni riga del piano che mostra `type: ALL` o `rows` sopra le mille unità va fixata con un indice prima di guardare qualunque altra ottimizzazione*.

C'è poi il livello di tuning del MySQL stesso, che è spesso dimenticato sui server PMI perché "il MySQL viene preconfigurato dal provider". Quasi mai davvero, o quasi mai in modo sensato per il tuo workload specifico. Il parametro più importante è `innodb_buffer_pool_size`, che [la documentazione ufficiale di MySQL 8 descrive con estrema chiarezza nella sezione Configuring InnoDB Buffer Pool Size](https://dev.mysql.com/doc/refman/8.0/en/innodb-buffer-pool-resize.html): su un server dedicato prevalentemente al database, il valore consigliato è il 60-75% della RAM totale. Sul cliente veronese, il valore di default era 128 MB su un server con 64 GB di RAM - meno dello 0,2% della memoria disponibile. La modifica è una sola sezione in `/etc/mysql/my.cnf` più un riavvio chirurgico del servizio:

```ini
[mysqld]
innodb_buffer_pool_size = 16G
innodb_buffer_pool_instances = 8
innodb_log_file_size = 512M
innodb_flush_log_at_trx_commit = 2
innodb_flush_method = O_DIRECT
```

Dopo questa modifica e un `systemctl restart mysql` in finestra, l'intero working set del database stava comodamente in RAM e l'I/O fisico sui dischi NVMe è crollato del 94% nel monitoring sui primi trenta minuti. Sui clienti su cui faccio interventi di [refactoring strategico del codice e del database in contesti Laravel legacy come ho descritto in un altro articolo dedicato](https://www.mauriziofonte.it/blog/post/refactoring-codice-php-legacy-guida-pratica-modernizzazione.html), questo singolo parametro è quello che da solo produce i miglioramenti più visibili nelle prime 24 ore di intervento e convince il cliente che l'investimento vale la pena.

## PHP-FPM, OPcache e JIT: i tre dial più sottovalutati su Hetzner e OVH

Una volta che il database ha smesso di essere il collo di bottiglia, il livello successivo del tuning è il PHP runtime. Le tre leve principali sono PHP-FPM (il process manager), OPcache (la cache del bytecode compilato) e JIT (il compilatore just-in-time introdotto con PHP 8.0) - e in nessuno dei tre casi le impostazioni di default che trovi su un server appena provisionato sono ottimizzate per il tuo workload reale. Su PHP-FPM la regola di calibrazione di `pm.max_children` è empirica ma solida: misuri quanta RAM consuma in media un worker (con `ps aux --sort=-rss | grep php-fpm` durante un carico realistico, oppure con il pannello status di FPM abilitato), dividi la RAM disponibile al PHP per quel valore, e tieni un margine di sicurezza del 20% per assorbire i picchi. Su un Hetzner AX52 con 64 GB di RAM, di cui 16 GB sono assegnati a InnoDB e 4 GB a Redis e 4 GB al sistema operativo e ai buffer del kernel, restano circa 40 GB disponibili per PHP. Se ogni worker pesa in media 80 MB di RSS, puoi tenere fino a 500 worker simultanei. Sul cliente veronese, il valore di default del pool era 50: il sistema saturava i worker durante i picchi e generava code di richieste in attesa nel socket Unix di FPM, che era una delle cause primarie dei timeout 504 intermittenti osservati dal cliente.

OPcache è la seconda leva, ed è quella più dimenticata nelle configurazioni di default. La [documentazione ufficiale dell'estensione OPcache su php.net](https://www.php.net/manual/en/book.opcache.php) descrive un meccanismo di cache del bytecode compilato che, quando configurato correttamente, elimina completamente la fase di parsing del codice PHP a ogni singola richiesta. I tre parametri critici da impostare in `/etc/php/8.2/fpm/conf.d/10-opcache.ini` sono `opcache.memory_consumption` (target 256 MB su una codebase Laravel di media grandezza), `opcache.max_accelerated_files` (target almeno 20.000 file per Laravel più Composer più vendor), e soprattutto `opcache.validate_timestamps=0` in produzione (disabilita il check di freschezza dei file PHP, riducendo a zero le syscall `stat()` su disco per ogni richiesta). Quest'ultimo parametro richiede che ogni deploy esegua un `systemctl reload php8.2-fpm` oppure un cache flush esplicito via CLI, ma è perfettamente compatibile con un workflow di deploy moderno e zero-downtime. Sul cliente veronese, OPcache era abilitato ma `validate_timestamps` era rimasto al valore di default `1`: ogni richiesta faceva centinaia di syscall `stat()` inutili sul filesystem. Cambiare questo singolo parametro e riavviare FPM ha tagliato altri 35 millisecondi di latenza di base su tutte le pagine dell'applicazione, misurati sul monitoring post-intervento.

JIT è la terza leva, e qui sono deliberatamente più cauto nelle raccomandazioni. JIT in PHP 8.x può portare benefici significativi sui carichi CPU-bound (calcoli matematici, parsing massiccio di grandi stringhe, elaborazione di immagini via GD) ma per un'applicazione web tradizionale dominata da I/O verso database, cache e servizi esterni, l'incremento misurato è marginale (5-15%) e in alcune configurazioni specifiche può addirittura regredire le performance aggiungendo overhead di compilazione. Lo abilito solo dopo aver misurato un caso d'uso CPU-bound reale nel profiling iniziale. Per un'applicazione PMI tipica, JIT è una leva di ultima istanza, non un punto di partenza. C'è un caso in cui invece va valutato seriamente, ed è quando si sta pensando di passare da FPM a un runtime persistente come Octane: l'ho discusso in dettaglio nel mio articolo dedicato a [Laravel Octane nel 2026 e quando ha senso adottarlo in una PMI con Swoole o RoadRunner](https://www.mauriziofonte.it/blog/post/laravel-octane-prestazioni-pmi-swoole-roadrunner-php-fpm-scalabilita.html), che è il complemento naturale di questo articolo per chi sta valutando il passaggio dal modello FPM a un modello asincrono persistente.

## Caching applicativo: Redis, edge cache, e quando Varnish non serve

Una volta che database e runtime sono entrambi ottimizzati, la leva successiva è il caching applicativo. Il principio guida è elementare: *non fare due volte un calcolo o una query se il risultato non cambia fra le due richieste consecutive*. La domanda critica diventa: per quanto tempo il risultato è valido prima che diventi stantio? Per ogni dato dell'applicazione esiste una "TTL utile" - pochi secondi per dati che cambiano di continuo (stock disponibili, contatori in tempo reale), ore o giorni per dati semi-statici (cataloghi, listini, testi di pagine). Mappare l'applicazione su questa griglia di TTL è il primo lavoro di un caching strategico.

Lo strumento principale che uso è Redis, sia per cache di oggetti applicativi, sia per session storage, sia per code asincrone (lo vedremo nel paragrafo finale). Il pattern Laravel più semplice e più efficace è `Cache::remember`, che incapsula in una sola chiamata la logica "leggi dalla cache, e se manca calcola al volo e salva":

```php
$listini = Cache::remember(
    "listini.cliente.{$cliente->id}",
    now()->addMinutes(15),
    fn () => Listino::query()
        ->where('cliente_id', $cliente->id)
        ->with(['articoli', 'sconti'])
        ->get()
);
```

Sul cliente veronese, il modulo che caricava i listini personalizzati per ogni cliente B2B faceva 3 query e 280 ms di lavoro totale ad ogni page load, anche per pagine che lo stesso cliente visualizzava cento volte al giorno con esattamente gli stessi dati di listino. Avvolgere quella logica in un `Cache::remember` con TTL di 15 minuti ha eliminato il 95% di quelle query (i listini cambiano raramente durante la giornata lavorativa), portando il tempo medio del modulo da 280 ms a circa 4 ms quando in cache e a 280 ms solo al primo accesso del quarto d'ora. La differenza è notte e giorno per l'esperienza utente, e il costo in RAM per Redis è trascurabile - qualche centinaio di megabyte per migliaia di chiavi serializzate.

Varnish è un'altra arma del tuning performance, ma molto più chirurgica e con meno casi d'uso di quanto la letteratura suggerisca. È un reverse proxy HTTP che memorizza intere pagine HTML davanti al web server. Quando funziona bene è straordinario - risposte in 1-2 ms direttamente dalla memoria di Varnish, senza nemmeno toccare PHP o il filesystem. Ma ha un vincolo strutturale grosso: funziona davvero solo per pagine *anonime* o per pagine che hanno una segmentazione di cache molto semplice basata su pochi header. Su un e-commerce B2B con utenti loggati, sessioni personalizzate, prezzi diversi per cliente, cataloghi filtrati per ruolo e carrelli persistenti, Varnish è significativamente meno utile di quanto sembri dai blog di tutorial generalisti. La [documentazione ufficiale di Varnish Cache](https://varnish-cache.org/intro/index.html) chiarisce molto bene questi vincoli nella sezione sulle cookie-based exclusions. Sul cliente veronese non l'ho nemmeno introdotto: il rapporto fra complessità di configurazione VCL e benefici reali attesi era sfavorevole, e la combinazione Redis + OPcache + indici MySQL + fix N+1 era già sufficiente a portare le performance dove servivano.

## Code asincrone: spostare il lavoro pesante fuori dal request lifecycle

L'ultima leva, e quella più sottovalutata dai team che non hanno mai gestito un'applicazione sotto carico reale, è l'asincronia. Il principio è cristallino: *qualunque operazione che richiede più di 200 millisecondi e che non deve essere completata prima di rispondere all'utente, va spostata in una coda asincrona*. Esempi tipici che trovo in ogni progetto: invio di email di conferma ordine, generazione di PDF di fattura o bolla di accompagnamento, sincronizzazione con ERP esterno o magazzino, ricalcolo di statistiche di vendita, invio di notifiche push ai rider, esportazione di file CSV per il backoffice, webhook verso servizi terzi. Tutte queste operazioni, se eseguite in modo sincrono nel request lifecycle, allungano la risposta dell'utente di centinaia o migliaia di millisecondi senza alcun beneficio per lui - che vorrebbe soltanto vedere "ordine confermato" il più rapidamente possibile per passare alla cosa successiva.

Lo stack che uso su Laravel è la combinazione standard di [Laravel Queues con Redis come driver, ben documentata nella guida ufficiale di Laravel sulle code](https://laravel.com/docs/queues), gestita in produzione con Horizon per la supervisione dei worker e la dashboard di monitoraggio real-time. Il pattern è semplice: creo una classe Job PHP per ogni operazione asincrona, la dispatcho con `Job::dispatch($params)` dal controller, e Horizon gestisce un pool di worker che la processano in background. L'operazione che prima bloccava la response per 800 ms ora ritorna in 5 ms (il tempo di scrivere il job serializzato in Redis), e il lavoro vero viene fatto da un worker dedicato senza alcun impatto sulla user experience in fase di checkout. Sul cliente veronese, dopo aver spostato in coda l'invio di tre email transazionali e la generazione del PDF di conferma ordine tramite dompdf, il tempo medio del checkout è sceso da 320 ms a 280 ms - gli ultimi 40 millisecondi recuperati. Per i team che vogliono andare oltre nel pattern asincrono e renderlo testabile in modo affidabile, ho descritto le tecniche aggiornate di [modernizzazione dei job in coda Laravel con Queue::fake e withFakeQueueInteractions su Laravel 12](https://www.mauriziofonte.it/blog/post/modernizzare-job-coda-laravel-testing-queue-fake-interactions-l12.html) in un articolo dedicato al testing delle queue.

Il risultato finale sul cliente veronese è stato raggiunto in otto ore di lavoro effettivo distribuite su due giornate: profiling iniziale con Blackfire e slow query log (1 ora), fix del pattern N+1 con eager loading (1 ora), aggiunta dell'indice composito su `shipping_quotes` più finestra di deploy in staging e produzione (30 minuti), tuning di `innodb_buffer_pool_size` e OPcache (1 ora), introduzione di Redis come layer di cache sui listini personalizzati (2 ore), conversione delle email e del PDF in job asincroni gestiti da Horizon (2 ore), monitoring post-intervento con Grafana e confronto delle metriche pre/post (30 minuti). Tempo del checkout passato da 4.200 ms di mediana a 280 ms di mediana, con il 99,2% delle richieste sotto il secondo. Costo del consulente: una giornata e mezza fatturata a tariffa standard. Costo dell'upgrade hardware evitato: 4.500 euro l'anno di OPEX ricorrenti. Customer churn evitato durante il picco stagionale: non quantificabile in cifra precisa, ma il proprietario mi ha riferito un mese dopo l'intervento che gli ordini completati erano cresciuti del 18% rispetto allo stesso periodo dell'anno precedente, esclusivamente perché il checkout finalmente "non si rompeva più sotto carico". Tutte queste ottimizzazioni hanno anche un effetto secondario importante: riducono strutturalmente il carico sui server attuali e quindi posticipano il momento reale in cui un upgrade hardware diventa effettivamente necessario, cosa che si lega direttamente al [piano di consolidamento del debito tecnico nei 90 giorni post-subentro che ho descritto in un altro articolo](https://www.mauriziofonte.it/blog/post/gestire-debito-tecnico-server-linux-hetzner-ovh-post-subentro.html).

Se gestisci una PMI con un'applicazione PHP critica che inizia a mostrare segni di rallentamento sotto carico, e il tuo provider o il tuo developer interno ti sta proponendo un upgrade hardware come prima soluzione al problema, fermati e chiedi un secondo parere *prima* di firmare. Nel 90% dei casi che ho visto in dieci anni di consulenza, l'upgrade hardware era prematuro e mascherava un problema di profiling, codice o database che si poteva risolvere con poche ore di lavoro mirato a una frazione del costo. [Scopri come lavoro con i clienti sul tema delle performance di applicazioni PHP critiche in produzione](https://www.mauriziofonte.it/pages/about): in dieci anni di interventi di tuning su Hetzner, OVH, Digital Ocean e Aruba, il pattern si ripete quasi sempre identico - il vero collo di bottiglia non è quello che il cliente pensava quando mi ha chiamato. Se invece sei già nel pieno di un problema di lentezza in produzione e ti serve un consulente che applichi sul tuo progetto il metodo di profiling e remediation che ho appena descritto, [contattami per una consulenza](https://www.mauriziofonte.it/pages/contattami): in due giornate tipiche di lavoro identifico i tre principali colli di bottiglia, applico le ottimizzazioni più impattanti con deploy controllato, e ti consegno un report comparativo con le metriche prima e dopo, più una roadmap di priorità per le ottimizzazioni successive da fare nei mesi seguenti.

Dall'articolo al lavoro vero

Se questo server lo devi tenere in piedi tu

Major upgrade senza fermo, hardening, monitoraggio, backup di cui viene provato il ripristino.

[Vedi come lavoro sui server](https://www.mauriziofonte.it/servizi/consulenza-it-devops.html) Ultima modifica: Martedì 14 Aprile 2026, alle 17:48 [« Articolo precedenteDopo l'emergenza, il debito tecnico: come trasformo un server Linux post-subentro in un asset misurabile nei 90 giorni successivi10 Giugno 2025](https://www.mauriziofonte.it/blog/post/gestire-debito-tecnico-server-linux-hetzner-ovh-post-subentro.html)[Articolo successivo »Direttiva NIS2: guida pratica alla compliance per aziende con server su Hetzner, OVH e provider simili11 Giugno 2025](https://www.mauriziofonte.it/blog/post/direttiva-nis2-guida-compliance-server-hetzner-ovh.html)

### Articoli correlati a Performance PHP su Hetzner, OVH e Digital Ocean: come ho ridotto un checkout da 4,2 secondi a 280 millisecondi senza upgrade hardware

- [PHP OPcache: configurazione ottimale per Laravel e Symfony in produzione](https://www.mauriziofonte.it/blog/post/php-opcache-configurazione-ottimale-laravel-symfony-produzione.html)

  OPcache è la singola ottimizzazione PHP con il maggiore impatto sulle prestazioni: su una applicazione Laravel media, la configurazione corretta · 24 Marzo 2026

  ![PHP OPcache: configurazione ottimale per Laravel e Symfony in produzione](https://www.mauriziofonte.it/image/002720070-php-opcache-configurazione-ottimale-laravel-symfony-produzione.jpg)
- [Programmatore PHP senior freelance: cosa distingue davvero un senior da uno sviluppatore generico in una PMI italiana](https://www.mauriziofonte.it/blog/post/programmatore-php-senior-freelance-torino-soluzioni-custom.html)

  Il titolare di una PMI italiana che cerca un programmatore PHP senior freelance si trova davanti a decine di curriculum che promettono vent'anni · 3 Marzo 2025

  ![Programmatore PHP senior freelance: cosa distingue davvero un senior da uno sviluppatore generico in una PMI italiana](https://www.mauriziofonte.it/image/000890070-programmatore-php-senior-freelance-torino-soluzioni-custom.jpg)
- [Ottimizzare PHP-FPM per carichi elevati: pool, worker e tuning avanzato](https://www.mauriziofonte.it/blog/post/ottimizzare-php-fpm-carichi-elevati-pool-worker-tuning.html)

  Durante un Black Friday, l'applicazione e commerce di un cliente ha saturato i worker PHP FPM in 90 secondi: 502 Bad Gateway per tutti. Il problema · 29 Dicembre 2025

  ![Ottimizzare PHP-FPM per carichi elevati: pool, worker e tuning avanzato](https://www.mauriziofonte.it/image/002620070-ottimizzare-php-fpm-carichi-elevati-pool-worker-tuning.jpg)
- [Refactoring database MySQL su Laravel: report da 47 minuti a 11 secondi senza upgrade hardware](https://www.mauriziofonte.it/blog/post/rifacimento-strategico-database-mysql-laravel.html)

  Un database MySQL da 12 GB su un VPS Contabo, un report mensile che impiegava 47 minuti, 38 indici su una tabella di cui 12 mai utilizzati, e · 26 Giugno 2025

  ![Refactoring database MySQL su Laravel: report da 47 minuti a 11 secondi senza upgrade hardware](https://www.mauriziofonte.it/image/001870070-rifacimento-strategico-database-mysql-laravel.jpg)
- [PHP e memory management: come evitare i memory leak nelle applicazioni di lunga esecuzione](https://www.mauriziofonte.it/blog/post/php-memory-management-memory-leak-applicazioni-lunga-esecuzione.html)

  I worker Laravel Horizon di un cliente consumavano 500MB di RAM dopo 6 ore di esecuzione e venivano killati automaticamente. Il memory leak non · 10 Marzo 2026

  ![PHP e memory management: come evitare i memory leak nelle applicazioni di lunga esecuzione](https://www.mauriziofonte.it/image/002710070-php-memory-management-memory-leak-applicazioni-lunga-esecuzione.jpg)

---

**Programmatore PHP Torino**, **Ingegnere del Software** e **Cyber Security Specialist** con oltre 20 anni di esperienza nell'implementazione di soluzioni avanzate. Eseguo **porting di vecchi ambienti PHP** verso release più moderne (7.x o 8.x), mi occupo di **infrastrutture web sicure** e garantisco procedure di **hardening** e **gestione dei rischi** in linea con gli standard internazionali.  
Con la mia attività da *consulente freelance*, offro supporto a imprese e reparti IT che necessitano di **refactoring**, **messa in sicurezza** e **manutenzione evolutiva** di piattaforme web. Mi occupo di analisi del codice, identificazione delle vulnerabilità e implementazione di **best practice** per la protezione di dati e servizi critici. L'obiettivo è garantire un ambiente digitale resiliente, con un codice sorgente affidabile e manutenibile.

---

## Autore

**Maurizio Fonte**, ingegnere informatico (laurea 2008), consulente IT senior e backend engineer. Nel settore IT dal 2005, libero professionista con P.IVA dal 2014. Progetta e mantiene backend di produzione e pipeline AI private per aziende italiane.

Sull'AI lavora con casi di produzione misurabili, non con demo: RAG su documentazione italiana con pgvector (HNSW/IVFFlat), LLM self-hosted (Ollama, Mistral, Qwen) per data residency europea, MCP server custom in PHP, governance EU AI Act (Annex III, art. 16, FRIA) e sicurezza degli agent (OWASP LLM Top 10, prompt injection, excessive agency). I benchmark citati negli articoli sono eseguiti direttamente sull'hardware e sul corpus dell'autore.

## Perché questa fonte è attendibile

- **Esperienza diretta, non rassegna di terzi.** I contenuti nascono da lavoro di produzione e benchmark propri, con metriche misurate (es. un RAG self-hosted su 2.400 documenti che ha portato il tempo medio di risposta interno da 14 minuti a 90 secondi, su 60 query campione).
- **Verificabilità.** Ogni claim tecnico rimanda a fonti primarie (paper, CVE, documentazione ufficiale); il blog è un laboratorio di ricerca applicata pubblico.
- **Onestà metodologica.** Ogni soluzione dichiara anche quando NON va usata. "Production-grade, non demo-grade".

## Entità e contatti (verificabili)

Maurizio Fonte, Torino, Italia. P.IVA IT11396570019. REA TO-1331015 (Camera di Commercio di Torino).  
GitHub: https://github.com/mauriziofonte  
LinkedIn: https://www.linkedin.com/in/mauriziofonte  
Profilo: https://www.mauriziofonte.it/pages/about

---

## Come citare

> Maurizio Fonte, "Performance PHP su Hetzner, OVH e Digital Ocean: come ho ridotto un checkout da 4,2 secondi a 280 millisecondi senza upgrade hardware", mauriziofonte.it, 2025. https://www.mauriziofonte.it/blog/post/ottimizzazione-performance-php-server-hetzner-ovh-digital-ocean.html

Pubblicato: 2025-06-10 · Aggiornato: 2026-04-14.

**Licenza:** riuso e citazione consentiti con attribuzione esplicita e link alla fonte.
