VibeInspect.aiBlog

Il tuo servizio sembra resiliente. Finché Replit moltiplica ogni errore

VibeInspect.ai · 23 agosto 2026 · 6 min di lettura

  • Replit
  • vibe-coding
  • performance
  • retry storm
  • resilienza

GitHub è cresciuto più in fretta dei suoi meccanismi di protezione

GitHub ha pubblicato un postmortem dopo un outage durato quasi otto ore. Il problema non è partito da una modifica al codice, ma da un picco di traffico che ha messo in crisi un componente infrastrutturale. La pressione si è poi propagata ad altri servizi, fino a causare errori di autenticazione e interruzioni a catena.

La notizia è GitHub now sees 2.9 billion commits a month — and it can’t keep up. Nel postmortem GitHub indica anche il lavoro su limiti ai tentativi, timeout più coerenti e isolamento delle dipendenze condivise.

Per il tuo prodotto, la lezione non è “devi avere l’infrastruttura di GitHub”. È più concreta: quando un servizio risponde lentamente o va in errore, il tuo codice prova di nuovo una volta, poi ancora, poi ancora? Se ogni istanza ripete la stessa richiesta nello stesso momento, un errore locale può trasformarsi in un sovraccarico generale.

Cosa significa se il tuo codice l’ha scritto Replit

Immagina di aver costruito con Replit un’app SaaS che riceve ordini e invia conferme tramite un servizio esterno. Il flusso sembra lineare:

  1. l’utente crea l’ordine;
  2. il backend salva i dati;
  3. una chiamata HTTP informa il provider dei pagamenti o delle notifiche;
  4. il provider risponde;
  5. l’app mostra lo stato aggiornato.

Poi il provider rallenta. La richiesta scade dopo dieci secondi. Il codice interpreta il timeout come un errore temporaneo e riprova. Anche il secondo tentativo scade. Il terzo parte mentre il primo potrebbe essere ancora in elaborazione.

Se hai cento richieste contemporanee, non hai più cento operazioni: ne puoi avere trecento, o mille, concentrate proprio quando un servizio è già sotto pressione. Questo è un retry storm, una tempesta di ritentativi. Il problema tecnico non è che il retry esista. È che manchino limiti, attese progressive, idempotenza e un modo chiaro per interrompere il flusso.

Un’app generata rapidamente può avere una funzione retryRequest() ordinata e ben tipizzata. Può anche avere test che verificano il successo normale e un singolo errore. Ma in produzione contano la combinazione tra timeout, concorrenza, code, webhook e stato persistito. Se una stessa operazione viene eseguita più volte, potresti duplicare un pagamento, creare notifiche ripetute o lasciare ordini in uno stato ambiguo.

Perché ora ti serve un audit del repository

Qui il passaggio mancante è un verdetto sul comportamento complessivo, non un altro controllo stilistico.

La domanda è: quando una dipendenza rallenta o fallisce, il repository limita il danno oppure continua ad aumentare il carico?

Per rispondere bisogna seguire il percorso reale della richiesta:

  • dove viene impostato il timeout;
  • quanti tentativi sono consentiti;
  • se il ritentativo usa un’attesa progressiva o parte subito;
  • se più worker possono ripetere la stessa operazione contemporaneamente;
  • se esiste un limite globale per servizio o per utente;
  • se le operazioni sono idempotenti;
  • come vengono gestiti gli errori dopo l’ultimo tentativo;
  • se una coda o un webhook può riaprire lo stesso flusso;
  • se il sistema ha un circuito di apertura quando la dipendenza continua a fallire.

Un audit VibeInspect analizza lo ZIP del repository e restituisce un PDF con score e verdetto. Nel piano Diagnostic, il report include file, righe ed evidenze: puoi vedere dove il retry viene configurato, come attraversa i servizi e quale combinazione può causare duplicazioni o carico a cascata.

Il risultato che serve al founder non è “abbiamo una funzione di retry”. È una risposta utilizzabile: PASS, oppure FAIL, con una catena di evidenze che spiega se il servizio degrada in modo controllato o se insiste fino a peggiorare l’incidente.

Questo è particolarmente importante nei progetti creati con Replit. La piattaforma ti permette di arrivare rapidamente a un’app funzionante, ma il fatto che il percorso felice sia rapido non dimostra che il percorso di errore sia governato. Il nemico non è l’AI. È spedire senza sapere cosa succede quando una dipendenza smette di collaborare.

Un audit deve ricostruire il fallimento, non contare i retry

Un report superficiale potrebbe segnalare ogni ciclo o ogni chiamata HTTP come possibile rischio. Non basta.

Un retry su una richiesta di lettura senza effetti collaterali non ha lo stesso peso di un retry su una conferma d’ordine. Un timeout breve può essere corretto per un endpoint interno, ma per un provider esterno può generare una situazione in cui il client non sa se l’operazione sia fallita o sia stata completata senza risposta.

L’evidenza forte collega almeno quattro elementi: l’azione iniziale, la politica di ritentativo, l’effetto prodotto dalla richiesta e il modo in cui il sistema registra lo stato. Se il codice invia una conferma di pagamento, ritenta senza chiave d’idempotenza e aggiorna il database solo dopo la risposta, hai un rischio tecnico concreto. Se la stessa chiamata passa anche da una coda con una propria politica di retry, il numero reale di tentativi può essere molto più alto di quello visibile nella singola funzione.

L’audit deve anche distinguere un limite dichiarato da un limite effettivo. Un costante MAX_RETRIES = 3 non protegge il sistema se il metodo viene richiamato da più livelli, se ogni worker applica tre tentativi o se un job fallito viene rimesso automaticamente in coda.

Cosa un linter non vede

Un linter controlla regole locali: sintassi, tipi, import, formattazione e alcuni pattern noti. Non ricostruisce sempre la pressione cumulativa prodotta da più servizi che ritentano la stessa operazione.

Non sa necessariamente che un timeout viene trattato come errore anche quando la richiesta potrebbe essere arrivata a destinazione. Non conosce la differenza tra una lettura ripetibile e un’operazione che crea un ordine, invia un messaggio o addebita un cliente. Non verifica da solo che il backoff sia sufficiente, che esista un limite per tenant o che un circuito interrompa le chiamate dopo una serie di errori.

Anche i test possono passare. Se usano una risposta immediata e un solo worker, non mostrano cosa accade con molte richieste simultanee. Se verificano solo il codice HTTP finale, possono ignorare duplicazioni, stati intermedi e carico generato dai tentativi precedenti.

Il linter ti dice che il codice rispetta certe regole. L’audit ti dice se il repository ha una strategia verificabile quando una dipendenza rallenta, fallisce o risponde in modo ambiguo.

Cosa fare questa settimana

  1. Scegli una dipendenza critica: pagamenti, email, autenticazione, ricerca o storage.
  2. Elenca tutte le chiamate che la raggiungono, comprese code, cron e webhook.
  3. Verifica timeout, numero massimo di tentativi e attesa tra un tentativo e l’altro.
  4. Controlla se più livelli applicano retry separati sulla stessa operazione.
  5. Classifica le chiamate in lettura, scrittura idempotente e scrittura con effetti economici o irreversibili.
  6. Verifica chiavi d’idempotenza, deduplicazione degli eventi e gestione degli stati incerti.
  7. Aggiungi un test con errori consecutivi e richieste concorrenti, non solo con un singolo timeout.
  8. Se hai usato Replit e non sai dire come il sistema si comporta sotto errore, fai un audit Diagnostic prima del prossimo rilascio.

Non devi rinunciare alla velocità di Replit. Devi aggiungere una prova sul comportamento che conta davvero: non solo “funziona quando tutto risponde”, ma “limita il danno quando una parte non risponde”.

Carica lo ZIP del repository e ottieni un verdetto con evidenze tecniche: avvia un audit Diagnostic.

Domande frequenti

Che cos’è un retry storm?

È una situazione in cui molti client o worker ripetono automaticamente richieste fallite nello stesso momento, aumentando il carico proprio mentre il servizio è già sotto pressione.

Un retry è sempre un problema?

No. Un retry può essere utile per errori temporanei, ma deve avere limiti, attese progressive e regole diverse per letture e operazioni che producono effetti.

Perché un retry può duplicare un’operazione?

Un timeout non dimostra sempre che l’operazione non sia arrivata a destinazione. Se il client ritenta senza idempotenza o deduplicazione, può creare più ordini, messaggi o addebiti.

Un linter rileva una retry storm?

Di norma no. Può individuare alcuni pattern locali, ma non ricostruisce il comportamento cumulativo tra client, worker, code, webhook, timeout e servizi esterni.

Quale piano VibeInspect è adatto a questo problema?

Il piano Diagnostic, perché include file, righe ed evidenze per verificare la catena tra chiamata, retry, stato persistito e possibile sovraccarico.