La cache può ridurre i tempi di risposta e il carico sui database o sui servizi esterni, ma da sola non corregge una query inefficiente né un’architettura con confini mal definiti. Una strategia di cache in PHP deve specificare cosa viene memorizzato, chi può riceverlo, per quanto tempo è valido e cosa accade se il meccanismo di storage non è disponibile.
Il criterio di successo non consiste soltanto nell’aumentare il tasso di hit. L’applicazione deve mantenere le proprie regole di business quando la cache è vuota, obsoleta o non disponibile. Per riuscirci, conviene iniziare misurando il problema e trattare la cache come un’ottimizzazione dal comportamento verificabile, non come la fonte primaria di verità.
Misurare prima di decidere cosa memorizzare

Individua innanzitutto gli endpoint lenti e le relative cause. Registra i tempi di risposta per endpoint, la latenza delle query, le chiamate ai servizi esterni, l’utilizzo della CPU e il volume delle richieste. Distingui le medie dai percentili più alti: una media accettabile può nascondere risposte molto lente per una parte degli utenti.
Cerca le operazioni ripetute il cui risultato cambia meno frequentemente della domanda: cataloghi, configurazione pubblica, contenuti pubblicati o aggregazioni costose. Verifica anche se la lentezza dipende da query senza indici, da un numero eccessivo di richieste, dalla serializzazione o da lavoro ripetuto all’interno della stessa richiesta. Migliorare la query può essere preferibile a memorizzare un risultato difficile da invalidare.
Definisci un valore di riferimento prima della modifica: prestazioni, carico e qualità dei dati osservata. Poi confronta lo stesso traffico o esegui un test riproducibile. Se non è possibile attribuire il miglioramento alla cache, sarà difficile valutarne i costi operativi e gli effetti collaterali.
Scegliere tra cache applicativa, HTTP e delle query
La cache applicativa memorizza valori che il codice PHP può riutilizzare, come i risultati di una query o una risposta calcolata. Può risiedere in memoria condivisa, in un servizio dedicato o in un altro backend compatibile con l’applicazione. È adatta quando più richieste hanno bisogno dello stesso risultato e se ne possono definire con precisione l’ambito e la validità.
La cache HTTP usa direttive come Cache-Control, ETag e meccanismi di validazione affinché browser o intermediari possano riutilizzare le risposte. È utile per risorse pubbliche o risposte la cui politica di privacy consente la memorizzazione. Le risposte personalizzate richiedono particolare attenzione: una policy pubblica può esporre dati, mentre una policy privata o che vieta la memorizzazione può ridurre questa possibilità, a seconda del flusso e degli intermediari coinvolti.
La cache delle query può essere una funzionalità del database, del driver o di un livello che conserva i risultati. Non va confusa con l’ottimizzazione dell’accesso ai dati: la cache non sostituisce indici, piani di query adeguati né transazioni. Prima di attivarla, chiarisci chi invalida le entry e se le letture devono riflettere immediatamente le scritture.
Scegli il livello più vicino al problema, non tutti contemporaneamente. Sovrapporre cache senza un modello esplicito può far sì che livelli diversi mantengano versioni differenti dello stesso dato e complicare la diagnosi.
Progettare chiavi, ambito e scadenza
Una chiave deve identificare tutti i fattori che modificano il risultato. Per esempio, una risposta di catalogo potrebbe dipendere dalla lingua, dalla valuta, dalla regione e dalla versione dei dati. Includi questi elementi in modo stabile e leggibile per facilitare la diagnosi; evita di inserire informazioni sensibili nella chiave.
Se il risultato dipende dall’utente, dal ruolo, dai permessi o dall’organizzazione, l’isolamento deve rispecchiarlo. Una chiave che include solo il nome dell’endpoint può far arrivare una risposta personalizzata a un’altra persona. Verifica anche come vengono condivise le entry tra processi e server. Se non puoi elencare in modo affidabile tutte le dimensioni che influiscono sul risultato, non memorizzare quella risposta come dato condiviso.
La scadenza deve derivare da una regola di business, non da un valore arbitrario. Una configurazione che cambia di rado può tollerare una finestra più lunga rispetto al saldo di un conto o allo stato di una prenotazione. Definisci la durata massima accettabile dell’obsolescenza e valuta variazioni casuali della scadenza quando molte entry simili potrebbero scadere nello stesso momento.
La scadenza temporale non sostituisce l’invalidazione in caso di modifiche importanti. È un limite massimo per impedire che un’entry rimanga memorizzata a tempo indefinito, non una garanzia di aggiornamento immediato.
Aggiornare e invalidare quando cambia la fonte
Scegli un meccanismo adeguato al livello di coerenza richiesto. L’invalidazione esplicita può essere eseguita dopo una scrittura: è diretta, ma può fallire se il processo si interrompe tra il salvataggio del dato e l’eliminazione dalla cache. Un’alternativa consiste nell’usare versioni nelle chiavi: quando cambia la fonte, si incrementa la versione e le entry precedenti non vengono più consultate. Questo richiede una gestione corretta della versione.
Nei sistemi basati su eventi, una modifica confermata può pubblicare una notifica per invalidare o ricalcolare i dati derivati. Se la consegna degli eventi non è affidabile, prevedi tentativi ripetuti, idempotenza e un meccanismo di riconciliazione. Non dare per scontato che aggiornare il database e il servizio di cache costituisca un’operazione atomica.
Per i dati che tollerano una breve obsolescenza, può essere opportuno servire un’entry scaduta mentre viene aggiornata in background. Questa tecnica non è adatta a tutte le informazioni: stabilisci quali dati possono essere trattati così, per quanto tempo può protrarsi l’obsolescenza e cosa succede se l’aggiornamento fallisce. La decisione deve dipendere dall’impatto della visualizzazione di un valore precedente.
Definire un comportamento sicuro in caso di errori
Verifica tre stati distinti: entry assente, entry scaduta e backend non disponibile. Per ciascuno, decidi se l’applicazione ricalcola il dato dalla fonte, restituisce un errore gestito oppure, quando è sicuro, fornisce un valore precedente. Una cache vuota deve essere uno stato normale all’avvio e non deve causare risultati errati.
Proteggi la fonte in caso di indisponibilità del backend. Se ogni richiesta avvia una query costosa alla scadenza della stessa chiave, può verificarsi un picco improvviso di carico. Tra le misure possibili ci sono limitare la concorrenza dei ricalcoli, riutilizzare temporaneamente valori sicuri oppure applicare limiti e timeout. La soluzione dipende dalla possibilità di servire il dato in forma obsoleta e dalla capacità della fonte.
Registra errori, latenze e fallimenti di lettura o scrittura senza includere valori privati. La cache è di norma una dipendenza per le prestazioni, non un’autorità sui dati: se la sua indisponibilità deve interrompere un’operazione critica, questa decisione deve essere giustificata esplicitamente.
Verificare coerenza e prestazioni con test riproducibili
Confronta gli scenari con cache disattivata, fredda e calda. Includi la prima richiesta dopo una scrittura, le modifiche di lingua o permessi, la scadenza simultanea e il fallimento del backend. Verifica sia i contenuti sia l’isolamento: due utenti con permessi diversi non devono ricevere risposte destinate all’altro.
Usa test automatizzati per le regole importanti relative alle chiavi e all’invalidazione e test di integrazione per verificare il comportamento con il backend reale o con un’alternativa rappresentativa. Nei test di carico, osserva hit e miss, latenza della cache, operazioni di ricalcolo, carico sulla fonte ed errori. Un tasso di hit elevato non dimostra che le risposte siano corrette.
Quando distribuisci una modifica, confronta metriche ed errori con un valore di riferimento. Predisponi un modo per disattivare l’ottimizzazione o tornare a un comportamento sicuro se compaiono dati obsoleti, crescita della memoria o una pressione imprevista sul database.
Lista di controllo per la gestione della cache

- Problema misurato: sono noti gli endpoint e le operazioni che giustificano la cache.
- Dati e fonte definiti: la cache non viene trattata come archivio primario.
- Chiave completa: include le dimensioni funzionali e i permessi rilevanti.
- Scadenza giustificata: corrisponde alla tolleranza del business all’obsolescenza.
- Invalidazione pianificata: è specificato quale evento aggiorna o sostituisce ogni entry.
- Errori gestiti: il comportamento per cache vuota, scaduta e non disponibile è definito.
- Monitoraggio operativo: vengono monitorati latenza, errori, hit e carico sulla fonte.
- Test di isolamento: vengono verificati utenti, ruoli, lingue e altri contesti pertinenti.
Una solida strategia di cache riduce il lavoro ripetuto senza modificare involontariamente il significato dei dati. Se ogni entry ha un ambito chiaro, una policy di validità e un piano verificabile per gestire gli errori, il team può valutarne i benefici e rimuovere o modificare l’ottimizzazione quando non è più adeguata.



