Il tuo repo generato da Cursor può trasformare un picco in un outage

VibeInspect.ai · 21 agosto 2026 · 5 min di lettura
- Cursor
- performance
- retry storm
- timeout
- vibe coding
GitHub ha scalato l’infrastruttura, ma i retry hanno ancora un prezzo
GitHub ha pubblicato un postmortem dopo un outage durato quasi otto ore. Il problema non è partito da una modifica al codice: un componente dell’infrastruttura non è riuscito a scalare quando il traffico ha raggiunto un nuovo picco. La pressione si è propagata ai servizi collegati, causando anche problemi di autenticazione.
Il dettaglio più utile per chi costruisce prodotti software non è il numero di commit gestiti dalla piattaforma. È la misura correttiva indicata nel postmortem: limiti coerenti ai retry e timeout rivisti per evitare retry storm e carico a cascata. La fonte è “GitHub now sees 2.9 billion commits a month — and it can’t keep up”.
Perché dovrebbe interessarti? Perché un’app può funzionare perfettamente in locale e fallire quando un provider rallenta, una connessione scade o due servizi iniziano a ritentare insieme.
Cosa significa se il tuo codice l’ha scritto Cursor
Cursor è molto bravo a trasformare una richiesta in un flusso completo: endpoint, client API, worker, gestione degli errori, schermata di loading. Il rischio non è aver usato l’AI. Il rischio è aver accettato una strategia di retry plausibile senza averne verificato gli effetti sull’intero sistema.
Il buco concreto è il retry storm.
Immagina questo flusso: il frontend chiama il tuo backend, il backend interroga un servizio esterno e un worker aggiorna lo stato nel database. Se il servizio esterno risponde lentamente, ogni livello può decidere autonomamente di ritentare. Il browser ritenta dopo due secondi. Il backend ritenta tre volte. Il worker riprende il job dalla coda. Il risultato non è resilienza: sono richieste duplicate che aumentano il carico proprio mentre il sistema è già sotto pressione.
In un repo costruito con Cursor puoi trovare facilmente:
- retry senza un limite globale di tentativi;
- timeout diversi tra client, API e worker;
- retry immediati, senza backoff e senza jitter;
- richieste non idempotenti ripetute dopo un timeout ambiguo;
- fallback che chiamano un secondo provider mentre il primo è ancora in difficoltà;
- log insufficienti per capire quale livello ha generato la richiesta originale.
Il codice può compilare, i test possono passare e il comportamento può sembrare corretto durante una demo. Il problema appare quando il sistema incontra il tempo reale.
Perché ora ti serve un audit sul repo
Un linter può dirti che una funzione è inutilizzata, che una variabile non è tipizzata o che una regola di stile non viene rispettata. Non può dirti se tre componenti stanno ritentando la stessa operazione con tempi incompatibili.
Un audit serve a ottenere un verdetto sul rischio tecnico del comportamento che hai spedito. Nel caso dei retry, significa ricostruire il percorso della richiesta attraverso il repo e verificare almeno quattro cose.
Primo: dove nasce il retry. Non basta cercare retry o retries. La stessa logica può essere nascosta in un client SDK, in un middleware HTTP, in una coda, in una libreria cloud o in un wrapper generato da Cursor. L’audit deve collegare questi punti e capire se il numero effettivo di tentativi è quello che pensi.
Secondo: che cosa succede quando la richiesta è ambigua. Un timeout non significa sempre che l’operazione non sia stata eseguita. Se hai creato un ordine, addebitato un pagamento o inviato un webhook, ritentare alla cieca può duplicare l’effetto. Qui servono idempotency key, deduplicazione o una strategia esplicita di riconciliazione.
Terzo: se i timeout hanno una gerarchia coerente. Un client che aspetta 30 secondi mentre il backend scade dopo 10 può creare una coda di richieste abbandonate. Un worker con timeout più lungo del provider può occupare risorse mentre il sistema continua a produrre nuovi job. Il verdetto deve considerare il budget di tempo dell’intera catena, non una singola funzione.
Quarto: se il sistema degrada o collassa. Quando il provider è lento, l’app dovrebbe ridurre il danno: limitare la concorrenza, aprire un circuit breaker, mettere in coda il lavoro, restituire uno stato intermedio o bloccare temporaneamente nuove richieste. Se ogni componente continua a insistere, il picco diventa un incidente.
Questa è la differenza tra “il codice sembra ragionevole” e “abbiamo evidenze sufficienti per decidere se il rischio è accettabile”.
Cosa un linter non vede
Il linter osserva il codice localmente. Il retry storm è un problema di interazione tra componenti, tempi e stato.
Non vede che il client ritenta una chiamata dopo un errore 502 mentre il backend ha già accodato l’operazione. Non vede che un job viene considerato fallito dal worker, ma completato dal provider. Non vede che il fallback verso un secondo servizio raddoppia il traffico. Non vede che un retry senza jitter sincronizza centinaia di richieste nello stesso istante.
Non vede nemmeno il contesto operativo: quali endpoint sono idempotenti, quali hanno effetti irreversibili, quali dipendenze condividono lo stesso limite di capacità. Può segnalare un catch vuoto, ma non può produrre da solo un verdetto sulla cascata che parte da quel catch.
Per questo un audit non è un linter più sofisticato e non è una promessa di codice corretto. È una verifica specialistica del repo che restituisce score, evidenze e, nel piano Diagnostic, riferimenti a file e righe. Non modifica il codice e non sostituisce le decisioni del team: rende visibile ciò che oggi stai solo intuendo.
Cosa fare questa settimana
- Mappa ogni chiamata esterna. Elenca API, database, code, webhook e provider AI. Per ciascuno annota timeout, numero di retry e comportamento dopo un errore.
- Scegli un solo proprietario del retry. Evita che frontend, backend e worker ritentino la stessa operazione senza coordinamento.
- Classifica le operazioni non idempotenti. Ordini, pagamenti, invio email e aggiornamenti di stato devono avere una protezione contro i duplicati.
- Aggiungi backoff con jitter e un tetto massimo. Il retry infinito non è resilienza: è traffico incontrollato.
- Verifica il caso peggiore. Simula un provider lento, non solo un provider completamente irraggiungibile. È lì che emergono le richieste abbandonate e le code che crescono.
- Fai audit del repo prima del prossimo rilascio. Se il problema è già tecnico e sai che il prodotto è destinato a utenti reali, ti serve un verdetto con evidenze, non un altro giro di suggerimenti generati dall’AI.
Hai spedito con Cursor? Bene. Ora verifica che il sistema sappia fallire senza trascinare tutto il resto con sé.
Carica il repo su VibeInspect.ai e scegli il piano Diagnostic: ottieni score, file, righe ed evidenze sui rischi tecnici che un linter non collega tra loro.
Domande frequenti
Che cos’è un retry storm?
È una cascata di richieste ritentate da più componenti nello stesso momento. Può aumentare il carico proprio quando un servizio è già lento o in difficoltà.
Perché un linter non rileva questo problema?
Perché il rischio nasce dall’interazione tra client, API, worker, code e servizi esterni. Un linter analizza soprattutto proprietà locali del codice.
Cursor genera automaticamente retry non sicuri?
Non necessariamente. Il rischio nasce dal trattare come definitiva una soluzione plausibile senza verificare timeout, idempotenza, backoff e comportamento dell’intera catena.
Quale audit VibeInspect serve per un problema di retry?
Il piano Diagnostic, perché il problema è tecnico e richiede evidenze con riferimenti a file e righe, oltre allo score del repository.