Scalare un SaaS dopo il lancio senza rompere il prodotto
Il lancio era la parte facile. Il tratto pericoloso è l'anno successivo, quando la crescita frattura in silenzio il prodotto semplice che L'ha portata fin qui. Questa è la guida calma e pratica per scalare senza il crollo al rallentatore.

Tutti festeggiano il lancio. Quasi nessuno La avverte della parte che viene dopo: quello strano anno, con le nocche bianche, in cui il prodotto che Le ha portato i primi cento clienti comincia a piegarsi sotto il peso dei mille successivi. Non accade nulla di drammatico. Le cose diventano semplicemente più lente, più instabili, più difficili da cambiare. Un martedì qualsiasi si accorge che una funzione che prima richiedeva un giorno ora ne richiede una settimana, e nessuno sa dire bene perché. È lì, non al lancio, che la maggior parte dei prodotti SaaS si vince o si perde in silenzio.
Ci siamo seduti con molti fondatori proprio a questo punto. Non stanno fallendo: è questo il bello che confonde. Il fatturato sale, il team cresce, le demo vanno bene. Ma sotto, il prodotto geme. I ticket di assistenza salgono più in fretta degli utenti. I deploy che prima erano noiosi ora arrivano con il fiato sospeso. La base di codice che un anno fa sembrava ingegnosa ora pare un campo minato dove ogni modifica rischia di far scattare qualcos'altro. Non hanno fatto nulla di male. Hanno solo superato ciò che avevano costruito, e nessuno aveva detto loro che doveva andare così.
Questa è quindi la guida che avremmo voluto in mano a più fondatori prima che comparissero le crepe. Non parla di hyperscale, Kubernetes o di ciò che un unicorno ha fatto a cinquanta milioni di utenti. Parla del mezzo noioso e decisivo: passare da funziona per pochi a funziona per molti, senza riscrivere tutto, senza spaventare i clienti né bruciare il team. L'obiettivo non è un'architettura perfetta. È un prodotto che continua a crescere invece di uno che comincia a rompersi in silenzio.
Cosa si rompe davvero quando un SaaS cresce
Ecco la parte che sorprende di più i fondatori: i problemi di scalabilità non arrivano quasi mai come il guasto drammatico per cui ci si prepara. Il server non prende fuoco. Il prodotto sviluppa invece una sorta di febbriciattola persistente. Pagine che si caricavano all'istante iniziano a impiegare tre secondi. Un report che girava bene per i primi clienti va in timeout per il grosso cliente che ha appena firmato. Lo stesso bug ricompare di continuo perché due parti del codice dipendono segretamente l'una dall'altra in un modo che nessuno ha documentato.
Ciò che davvero si rompe raramente sono i Suoi server: sono i Suoi presupposti. All'inizio ha costruito per la forma dei primi utenti: pochi account, dati ridotti, flussi semplici, tutti più o meno uguali. La crescita non aggiunge solo più dello stesso. Aggiunge varietà. Un cliente con dieci volte i dati. Un team che usa una funzione in un modo che non aveva mai immaginato. Un picco alle nove del lunedì, quando tutti accedono insieme. Ognuno viola in silenzio un presupposto cementato nel Suo codice un anno fa, quando violarlo era impensabile.
“Il Suo prodotto non si rompe perché ha più utenti. Si rompe perché quegli utenti sono più diversi tra loro di quanto lo siano mai stati i primi.”
I quattro punti in cui tende a manifestarsi per primo sono prevedibili. Il database è quasi sempre il canarino: query istantanee su tabelle piccole rallentano man mano che i dati crescono. L'endpoint lento: una o due pagine che fanno troppo lavoro per richiesta, a posto finché il traffico non si accumula. Il deploy fragile, dove rilasciare qualunque cosa è diventato spaventoso perché il codice è troppo aggrovigliato per ragionarci. E il carico di assistenza, che non è affatto infrastruttura ma è il segnale precoce più sincero che il prodotto non corrisponde più al modo in cui le persone lo usano davvero.

La trappola di risolvere problemi che non ha ancora
Prima di parlare di come correggere, un avvertimento che ha salvato più prodotti di qualsiasi ottimizzazione. La minaccia più grande per un SaaS in crescita non è ignorare la scala: è inseguirla troppo presto. Nel momento in cui un fondatore avverte il primo rallentamento, l'istinto è afferrare l'architettura letta su un famoso blog di ingegneria. Microservizi. Una coda di messaggi. Un assetto multiregione. Sharding del database prima che abbia un milione di righe.
È così che si passano sei mesi e una fortuna a costruire infrastruttura per una scala che non si è raggiunta, mentre il prodotto vero si ferma. Peggio, ora ha reso più difficile ogni modifica futura, perché un sistema distribuito è enormemente più complesso da costruire e da debuggare di quello semplice che aveva. Ha barattato un problema che non aveva ancora con uno garantito che ha oggi: non si rilascia nulla.
La disciplina qui è la stessa che fa i buoni prodotti in primo luogo: risolva il problema che ha davanti, non quello che la lusinga immaginare. Un monolite noioso e ben compreso che può cambiare in fretta scalerà meglio di un sistema distribuito alla moda che ha paura di toccare. La complessità è un costo che paga ogni singolo giorno, non un acquisto una tantum.
Misuri prima di cambiare qualunque cosa
Quasi ogni fondatore che incontriamo in questa fase è convinto di sapere dov'è il problema. Si sbaglia nella metà dei casi, non per sciatteria, ma perché l'intuito è un pessimo profiler. La parte di codice che sembra lenta spesso va bene; il vero colpevole è qualche query silenziosa che gira quaranta volte su una pagina a cui nessuno ha pensato. Non si può correggere ciò che non si è misurato, e tirare a indovinare qui è il modo in cui i team passano settimane a ottimizzare la cosa sbagliata.
Non Le serve uno stack di osservabilità sofisticato per iniziare. Le servono tre numeri noiosi sempre sott'occhio. Quali endpoint sono più lenti, e quanto sotto traffico reale. Quali query del database consumano più tempo totale: non la singola query più lenta, ma quella il cui tempo si somma su migliaia di chiamate. E dove gli errori accadono davvero, con abbastanza contesto per riprodurli. Con questi tre, la nebbia di solito si dirada nel giro di un giorno.
- 1Attivi il monitoraggio di baseTempi di risposta per endpoint, tassi di errore e logging delle query lente sul database. Gli strumenti gestiti lo fanno in un pomeriggio. Non può migliorare un numero che non vede.
- 2Trovi i veri primi treOrdini per tempo totale consumato, non per istinto. Tre colpevoli concentrano quasi sempre la maggior parte del dolore. Li annoti: quella è la Sua vera roadmap.
- 3Ne corregga uno, rimisuriCambi una sola cosa, poi ricontrolli i numeri. Confermi che ha aiutato prima di proseguire. Due modifiche insieme e non saprà mai quale contava.
- 4Si fermi quando è abbastanza buonoDefinisca 'abbastanza veloce' prima di iniziare: per esempio, ogni pagina sotto un secondo al carico attuale. Oltre, ottimizzare è una voragine di tempo, non una vittoria.
Quell'ultimo passo conta più di quanto sembri. Il lavoro sulle prestazioni dà genuinamente dipendenza; c'è sempre un altro millisecondo da limare. Ma i Suoi clienti non sentono la differenza tra 200 ms e 120 ms, e le ore spese a inseguirla sono ore non dedicate alla funzione che farebbe davvero crescere l'azienda. Misuri, corregga i primi tre, dichiari vittoria, vada avanti.
Il database è quasi sempre il primo muro
Se dovessimo scommettere dei soldi su dove un SaaS in crescita incontra il suo primo vero tetto, scommetteremmo sul database ogni volta. È la parte del sistema in cui le piccole decisioni iniziali si sommano nel modo più duro. Una query senza indice gira in un lampo su mille righe e si inceppa su un milione. Il codice non è cambiato. I dati sì, e i dati non fanno che crescere.
La buona notizia è che il database è anche dove vivono le correzioni più economiche e di maggiore impatto. La classica è l'indice mancante: una sola riga che trasforma una query da più secondi in una istantanea, perché il database smette di scandire ogni riga per trovare le poche che gli servono. Subito dietro c'è il problema delle query N+1: una pagina che, invece di porre una domanda, pone in silenzio al database la stessa piccola domanda centinaia di volte in un ciclo. Entrambi sono comuni, entrambi sono invisibili finché non si guarda, ed entrambi di solito si correggono in un giorno una volta trovati.
C'è una sequenza su cui appoggiarsi qui, e conviene seguirla in ordine invece di saltare alla fine. Corregga prima le query: indici, N+1, il report lento. Poi aggiunga caching per i dati letti di continuo ma che cambiano di rado. Solo dopo ha senso parlare di repliche di lettura, istanze più grandi o di separare i dati. La maggior parte dei prodotti SaaS non ha mai bisogno dei passaggi successivi. Aveva solo bisogno che i primi fossero fatti bene.

Scalare il prodotto significa scalare il modo in cui lo si cambia
Ecco lo spostamento che coglie i fondatori impreparati: superato un certo punto, scalare smette di riguardare il prodotto che regge più utenti e inizia a riguardare il Suo team che regge più cambiamento. Quando eravate Lei e uno sviluppatore, ognuno teneva l'intero sistema in testa. Poteva cambiare qualunque cosa perché sapeva cosa avrebbe toccato. A cinque o dieci persone, quel modello mentale va in frantumi, e il codice che dava per scontato che tutti sapessero tutto diventa un fardello.
Questa è la vera ragione per cui i deploy fanno paura. Non è che il codice sia peggiorato da un giorno all'altro; è che nessuno riesce più a prevedere del tutto il raggio d'impatto di una modifica. La soluzione non è l'eroismo né un blocco dei rilasci. È investire nelle impalcature poco affascinanti che permettono a un team più grande di muoversi senza pestarsi i piedi: una suite di test automatici che intercetta le rotture ovvie, deploy che sono routine invece che cerimonia, e un modo per spegnere un rilascio sbagliato in pochi secondi invece di correre ai ripari.
- Una suite di test che copra la manciata di flussi la cui rottura sarebbe catastrofica: login, pagamento, azione principale. Non tutto; i pochi critici.
- Deploy che girano con un pulsante, non un rito, così che rilasciare poco e spesso diventi sicuro invece che logorante.
- Un modo rapido per fare rollback, così che un rilascio sbagliato sia un evento di cinque minuti, non un incidente di tutta la notte.
- Feature flag, così da poter rilasciare codice prima a pochi clienti e spegnerlo all'istante se si comporta male.
- Documentazione sufficiente perché le ferie di una persona non blocchino un'intera area del prodotto.
Niente di tutto questo compare in una demo. Niente di tutto questo aggiunge direttamente una funzione. Ed è esattamente il lavoro che separa un prodotto che continua ad accelerare da uno che rallenta a ogni nuova assunzione. I team che scalano bene sono quelli che trattano la propria capacità di cambiare il prodotto in sicurezza come una funzione a sé, perché su larga scala è precisamente quello che è.
Una breve storia dal punto di rottura
Per renderlo concreto, ecco un caso composito tratto da lavori che abbiamo svolto: dettagli sfumati, forma fedele alla realtà. Un piccolo gestionale SaaS per squadre di assistenza sul campo era partito bene ed era cresciuto fino a qualche centinaio di aziende paganti. I fondatori erano entusiasti ed esausti in egual misura. Poi ha firmato il loro cliente più grande di sempre: un'impresa con più utenti e più dati storici dei dieci clienti precedenti messi insieme.
Nel giro di una settimana, la dashboard in cui tutti vivevano si era rallentata fino a strisciare per quel cliente, e, curiosamente, anche per tutti gli altri. I ticket di assistenza sono schizzati. I fondatori hanno supposto di aver bisogno di un server molto più grande e si preparavano a una ri-architettura dolorosa e costosa. È stato quel momento a portarci dentro, e l'istinto era comprensibile ma sbagliato.
Non abbiamo toccato l'architettura. Abbiamo attivato il logging delle query lente e osservato per un pomeriggio. Il colpevole era quasi imbarazzante per piccolezza: la dashboard principale caricava l'elenco lavori di ogni utente con un classico schema N+1, sparando una query per ogni lavoro. Per un cliente piccolo significava qualche decina di query innocue. Per il nuovo gigante significava migliaia per ogni caricamento di pagina, il che, su infrastruttura condivisa, trascinava giù l'intero sistema per tutti.
La lezione che i fondatori ne hanno tratto non era tecnica. Era che lo spaventoso problema di scalabilità che avevano immaginato, quello che richiedeva una ricostruzione e una raccolta fondi, una volta misurato era una correzione di due giorni nascosta dietro un sintomo inquietante. Stavano per passare mesi a risolvere il problema sbagliato. Quel divario, tra la crisi immaginata e quella misurata, è dove si spreca gran parte del denaro della scalabilità.
Quando è davvero il momento di ricostruire un pezzo
Tutta questa cautela verso la scalabilità prematura può leggersi come mai rifattorizzare, mai ricostruire. Non è così. A volte una parte del prodotto ha davvero raggiunto la fine della sua vita, e rattopparla ancora è la scelta costosa. Il trucco è distinguere un vero limite strutturale dai normali dolori di crescita che una correzione misurata risolverebbe.
Il segnale onesto è questo: ricostruisca un componente quando il costo di cambiarlo è diventato stabilmente più alto del costo di sostituirlo. Non quando è brutto: il codice brutto ma stabile e toccato di rado va bene. Cerca una parte del sistema in cui ogni modifica è lenta e rischiosa, in cui gli stessi bug continuano a tornare, in cui i nuovi sviluppatori non possono lavorare in sicurezza, e in cui ha già provato le correzioni più economiche e ha sbattuto contro un muro. Quando diverse di queste condizioni sono vere insieme, una riscrittura mirata di quell'unico pezzo è la scelta giusta.
| Segnale | Probabilmente solo una correzione | Probabilmente una ricostruzione |
|---|---|---|
| Sintomo | Una pagina o query lenta | Ogni modifica in un'area è lenta e rischiosa |
| Bug | Occasionali, correggibili | Gli stessi bug continuano a tornare |
| Correzioni economiche | Non ancora provate | Già esaurite, ancora bloccati |
| Ambito | Contenuto a una funzione | Si estende a tutto il modulo |
| Mossa giusta | Misurare e rattoppare | Ricostruire quell'unico pezzo, con cura |
E quando ricostruisce, ricostruisca un pezzo, non il prodotto. La riscrittura completa da zero è il canto delle sirene della scalabilità, ciò che sembra pulito e finisce per affondare un anno mentre i concorrenti rilasciano. Sostituisca l'unico componente marcio, dietro un confine netto, mentre il resto del prodotto continua a girare e a guadagnare. Chirurgico, non eroico.

Ha sbattuto contro il muro e non sa se è una correzione o una ricostruzione?
È la decisione costosa da sbagliare ed economica da azzeccare. Misureremo dove il Suo prodotto è davvero sotto sforzo e Le diremo con onestà se è una correzione di due giorni o qualcosa di più profondo, prima che qualcuno scriva una riga di codice nuovo.
Scopra il nostro approccio allo scalare il softwareDomande frequenti
Come faccio a sapere se il mio SaaS sta per sbattere contro un muro di scalabilità?
Dovrei passare ai microservizi per scalare?
È più economico ottimizzare il codice o semplicemente comprare un server più grande?
Quando una riscrittura completa è davvero la decisione giusta?
Quanto dovrei investire nella scalabilità prima di avere gli utenti?

Have a nice day è uno studio software che aiuta le piccole e medie imprese a digitalizzarsi — automazione, IA e software su misura che funziona nelle operazioni quotidiane, non solo sulle slide.