Alta disponibilità VS Resilienza

Alta disponibilità e resilienza non sono la stessa cosa (e confonderle ti costa caro)

C’è un centralino telefonico che, alle nove di un martedì qualunque, comincia a rallentare.

Niente di drammatico. Una linea su dieci risponde con due secondi di ritardo. Il problema vero, però, non è il ritardo: è quello che fanno le persone. Non lo sanno che è un intoppo passeggero. Quindi riagganciano e richiamano. Subito. Con più insistenza.

E più richiamano, più il centralino si intasa. Quel rallentamento da due minuti diventa un’ora di linee occupate. Il guasto iniziale era piccolo. **A farlo esplodere non è stato il guasto, ma la reazione a catena.**

Tieni a mente questa immagine. Perché è esattamente ciò che succede dentro l’infrastruttura della tua azienda quando qualcosa va storto, proprio nel momento in cui pensavi di essere al sicuro.

“Ma io ho due server, il failover, i backup…”

Verissimo. Hai fatto le cose per bene. Due server invece di uno. Failover automatico. Backup notturni. Le dashboard sono tutte verdi. Sulla carta sei “sempre attivo”.

Hai investito in alta disponibilità. Ottimo.

E allora perché un giorno qualunque tutto si pianta lo stesso, e la dashboard continua a dirti che va tutto bene?

Perché alta disponibilità e resilienza sono due cose diverse. E dare per scontato che la prima includa la seconda è l’errore che si paga più caro.

Proviamo con un esempio

Vediamo se riesco a spiegarmi meglio. Pensa alla tua auto.

L’alta disponibilità è avere la ruota di scorta nel bagagliaio. Se ne fora una, ne hai un’altra pronta. È ridondanza: un componente si rompe, ne entra in funzione un altro identico. 

La resilienza è un’altra storia. È saper guidare quando piove, quando l’asfalto è viscido, quando davanti a te qualcuno inchioda all’improvviso. Non è avere un pezzo di ricambio: è il modo in cui ti comporti quando le cose vanno male sul serio.

Detto in modo brutale:

L’alta disponibilità ti protegge dal guasto di un singolo componente. La resilienza ti protegge dal comportamento dell’intero sistema quando un componente fa i capricci.

E il punto è proprio questo: i sistemi non cadono quasi mai perché un pezzo si rompe. Cadono perché, quando quel pezzo rallenta, tutto il resto reagisce nel modo sbagliato.

I tre modi in cui un guasto si propaga

Vediamoli in concreto, perché sono i tre colpevoli che ritroviamo praticamente in ogni incidente serio.

1. La tempesta di tentativi.
È il nostro centralino. Un servizio rallenta, le richieste vanno in timeout, e chi le ha mandate riprova. Subito, e magari più del normale. Solo che mentre quel servizio arrancava, ora gli arriva il triplo del traffico. Così rallenta ancora di più. Così arrivano altri tentativi. È una valanga che si autoalimenta. Un problemino da trenta secondi diventa un blocco da mezz’ora. Non perché il guasto fosse grave, ma perché il sistema lo ha amplificato da solo.

2. Il picco di latenza.
Stavolta non si ferma niente. Tutto risponde. Solo che risponde piano. E la lentezza, a volte, è peggio del blocco. Perché ogni richiesta lenta tiene occupata una risorsa, un thread o una connessione, che resta lì in attesa invece di liberarsi. Le richieste si accodano. La coda cresce. E a un certo punto non c’è più nessuno libero a rispondere, anche se tecnicamente non è “andato giù” niente. E così il sistema è fermo a tutti gli effetti, anche se nessuna spia si è accesa.

3. Il guasto parziale.
Questo è il più subdolo. Non si rompe tutto: va in errore una richiesta su venti. Oppure smette di funzionare una sola funzione, il login, il checkout, l’invio di un documento, mentre tutto il resto gira. La dashboard ti dice “il 95% delle richieste è OK” e resta verde, serena. Peccato che quel 5% che fallisce sia proprio l’operazione da cui passano i tuoi incassi. La media, in casi così, ti frega: ti racconta che va tutto bene mentre la cosa più importante è inchiodata.

Ed è qui il cuore della questione: questi tre guasti le dashboard standard non te li mostrano. Non finché non è troppo tardi. 

Un lunedì di fine mese

Andiamo nel concreto. Immagina una software house che gestisce in cloud il gestionale di una trentina di aziende clienti. Server ridondati, failover, backup. Sulla carta, infrastruttura solida.

Arriva la fine del mese. Tutti i clienti, più o meno nelle stesse ore, lanciano le chiusure contabili e i report pesanti. Il database, che di solito lavora tranquillo, comincia a rallentare sotto il peso di decine di query lunghe in contemporanea.

Da qui in poi ci sono due strade.

Nella prima, l’applicazione non ha previsto questo scenario. Le query lente non vengono interrotte, le connessioni al database restano aperte in attesa, il pool si esaurisce. A quel punto non si bloccano solo i report: si blocca il gestionale per tutti, anche per chi voleva solo emettere una fattura. Risultato: quasi 3 ore di servizio inutilizzabile per l’intero parco clienti, e un’ora buona passata a capire cosa stesse succedendo, perché lato monitoraggio i server risultavano accesi e in salute.

Nella seconda, la stessa software house aveva messo in conto che i report potessero diventare ingombranti. Le query pesanti girano su una replica separata e hanno un tempo massimo oltre il quale vengono interrotte. Quando il carico sale, il sistema mette i report in coda e mostra un onesto “elaborazione in corso, ti avvisiamo appena è pronto”, mentre fatturazione e operazioni quotidiane continuano a funzionare senza accorgersi di niente. Risultato: nessun blocco generale, e i report semplicemente più lenti per venti minuti

Stesso evento. Stessa ridondanza. Esito opposto.

La differenza non è stata l’alta disponibilità, ce l’avevano in entrambi i casi. La differenza è stata la resilienza, cioè cosa fa il sistema nei primi trenta secondi in cui qualcosa va storto.

Nella prima versione, quella chiusura di fine mese se la ricordano ancora tutti. Nella seconda, non se n’è accorto nessuno. Che, a pensarci, è il complimento più grande che si possa fare a un’infrastruttura.

In una tabella, per chi va di fretta

Alta disponibilità Resilienza
Domanda a cui risponde “E se si rompe un pezzo?” “E se il sistema si comporta male?”
Soluzione tipica Ridondanza, failover Gestione intelligente del degrado
Ti protegge da Guasto di un componente Propagazione del guasto
Cosa fa sotto stress Sostituisce il pezzo rotto Assorbe il colpo e rallenta invece di spegnersi
Cosa misura “Sono acceso?” “Sto facendo davvero il mio lavoro?”

Da dove si comincia, in pratica

Non serve riprogettare tutto domani mattina. Serve farsi le domande giuste. La prima: quali funzioni della tua azienda non possono fermarsi, e quali invece possono aspettare mezz’ora? Non è un esercizio teorico. Decidere in anticipo cosa puoi permetterti di rallentare o spegnere durante un guasto è ciò che distingue un disservizio gestito da un disastro improvvisato. La seconda: da quali dipendenze esterne dipendi senza averlo deciso davvero? Un’API di pagamento, un servizio di posta, un fornitore cloud. Ognuna di queste è una porta da cui un guasto altrui può entrare in casa tua. La terza, la più scomoda: hai mai provato a metterlo sotto stress di proposito, in un ambiente controllato? Perché un piano che non hai mai testato non è un piano, è una speranza. Vale lo stesso per il backup e il disaster recovery: finché non provi a ripristinare per davvero, non sai se funziona.

Inserto per i tecnici

Se sei un IT manager o un tecnico, questa sezione fa per te. Se non lo sei, puoi saltarla tranquillamente. I pattern che fanno la differenza tra “altamente disponibile” e “resiliente” sono noti, ma vanno adottati con intenzione, non a caso.
  • Circuit breaker. È lo strumento che “stacca la spina” nella nostra seconda software house. Quando una dipendenza supera una soglia di errori o di latenza, il breaker passa in stato open e fa fallire le chiamate immediatamente (fail-fast) invece di tenerle in attesa. Dopo un tempo di prova passa in half-open per testare se il servizio è tornato. È il singolo pattern che evita più tempeste di tentativi.
  • Retry con backoff esponenziale e jitter. Riprovare va bene, ma non subito e non tutti insieme. Il backoff esponenziale distanzia i tentativi; il jitter (una componente casuale) evita che migliaia di client riprovino sincronizzati allo stesso istante, il classico thundering herd. Retry senza jitter è benzina sul fuoco.
  • Timeout e deadline budget. Ogni chiamata deve avere un timeout aggressivo e sensato. Senza timeout, una dipendenza lenta consuma thread e connessioni finché non si esaurisce il pool. Meglio ancora: propagare un deadline budget lungo la catena di chiamate, così nessuno aspetta oltre il tempo che ha senso aspettare.
  • Bulkhead. Isolare le risorse per funzione, come le paratie stagne di una nave. Se il pool di connessioni dei report si satura, non deve trascinarsi dietro anche la fatturazione. È esattamente ciò che ha tenuto in piedi il resto del gestionale.
  • Load shedding e graceful degradation. Sotto pressione, è meglio rifiutare in modo controllato una parte delle richieste (e magari le meno critiche) che collassare su tutte. Definisci in anticipo cosa degradare.
  • Idempotenza. Se introduci retry, le operazioni devono essere idempotenti, o rischi pagamenti doppi e dati incoerenti. Idempotency key dove serve.
  • Osservabilità seria. Qui sta il motivo per cui “la dashboard era verde”. Un health check superficiale verifica che l’host risponda, non che il flusso di business funzioni. Servono deep health check, synthetic monitoring sui percorsi critici (login, checkout) e soprattutto metriche di latenza p95/p99, non la media. La media nasconde il guasto parziale; il p99 te lo mostra. Affianca SLO ed error budget per ragionare in termini di “quanto disservizio è accettabile” invece che “su/giù”.
  • Chaos engineering. Iniettare guasti controllati in pre-produzione (latenza, errori, indisponibilità di una dipendenza) per scoprire le reazioni a catena prima che lo faccia la realtà di un martedì qualunque.

Prima o poi succede a tutti

C’è una cosa scomoda da accettare: il guasto, prima o poi, arriva. A tutti. Quindi il costo della resilienza non è una spesa in più che potresti evitare. È solo la versione piccola, prevedibile e pianificata di un costo che altrimenti pagheresti grande, improvviso e nel momento peggiore. Progettare timeout, circuit breaker e degradazione controllata costa tempo e disciplina. Poco. Un fermo totale costa ore di blocco, ore di lavoro per capire cosa succede mentre le dashboard mentono, clienti che intanto guardano altrove e una reputazione che si incrina in un pomeriggio. Molto. Tre domande da portarti a casa:
  • Quanto mi costa davvero, in euro, un’ora di fermo della mia funzione più critica?
  • Quante delle mie dipendenze potrebbero, oggi, trascinarsi dietro tutto il resto?
  • Sto decidendo io quando spendere per la solidità, o lo sta decidendo il prossimo guasto al posto mio?

Il punto, in breve

Un sistema solido non è quello che non cade mai. È quello che, quando qualcosa cade, sa già cosa fare nei trenta secondi successivi.

In sintesi:

  • Alta disponibilità non è resilienza. La ridondanza ti copre dal componente rotto, non dal sistema che reagisce male.
  • I guasti nascono piccoli. A ingrandirli sono tempeste di tentativi, picchi di latenza e reazioni a catena.
  • Le dashboard tutte verdi non vogliono dire “tutto a posto”. I guasti parziali si nascondono nelle medie: servono p99, monitoraggio sintetico e SLO.
  • La resilienza la prepari prima, a mente fredda. Nel mezzo di un guasto non te la inventi, e un piano mai testato vale quanto un buon proposito.

La domanda, allora, non è se la tua infrastruttura è accesa. È se sa cosa fare quando qualcosa smette di girare come dovrebbe.

In Cloudable costruiamo infrastrutture che non si limitano a restare in piedi: sono pensate per assorbire i colpi e continuare a lavorare. Se vuoi sapere come si comporterebbe la tua sotto stress, possiamo analizzarla insieme. Meglio scoprirne i limiti a tavolino oggi, che sul campo domani.

Parliamone