L’era del «pentimento da microservizi»: perché i team stanno tornando, in silenzio, ai monoliti
6 min di lettura

L’era del «pentimento da microservizi»: perché i team stanno tornando, in silenzio, ai monoliti

Perché startup e team di sviluppo tornano ai monoliti modulari dopo aver scoperto i costi operativi nascosti dei microservizi adottati troppo presto.

Inizia a leggere

Per un po’ i microservizi sono sembrati il passo successivo ovvio per qualsiasi prodotto software serio.

Appena una startup iniziava a crescere, prima o poi il discorso sull’architettura finiva sempre lì: spezzare l’applicazione in servizi più piccoli. L’autenticazione diventava un servizio a sé. I pagamenti venivano separati. Le notifiche finivano da un’altra parte. In poco tempo un prodotto nato come un’applicazione tutto sommato semplice poteva ritrovarsi con un numero sorprendente di servizi dietro le quinte.

E, a dirla tutta, c’erano buoni motivi per farlo.

I microservizi risolvono problemi reali. Permettono ai team di rilasciare parti del sistema in modo indipendente, di scalare carichi di lavoro specifici senza scalare tutto il resto e di dare ai team più grandi la responsabilità di parti diverse del prodotto.

Per le aziende che lavorano su scala davvero grande, questa separazione può essere utilissima.

Il problema nasce quando l’architettura arriva prima del problema.

Una startup di cinque persone con qualche migliaio di utenti non ha le stesse esigenze architetturali di un’azienda con centinaia di sviluppatori e milioni di richieste al giorno. Eppure è sorprendentemente facile costruire il prodotto piccolo come se quel futuro fosse già arrivato.

È lì che comincia il pentimento da microservizi.

Il problema non sono i microservizi

Vale la pena chiarire una cosa: questo non è un articolo contro i microservizi.

Non sono il male. Nella situazione giusta sono utilissimi.

Il problema è adottarli solo perché sembrano il modo «giusto» di costruire un’applicazione moderna, e non perché il prodotto ne abbia davvero bisogno.

Immagina una piccola applicazione con autenticazione, pagamenti, profili utente e notifiche.

Potresti trasformare ognuna di queste parti in un servizio a sé. Su un diagramma dell’architettura il risultato potrebbe sembrare pulito e ben organizzato.

Ma adesso ogni servizio ha bisogno di un processo di deploy, monitoraggio, log, configurazione, autenticazione, gestione degli errori e documentazione.

Quella che poteva essere una chiamata di funzione dentro la stessa applicazione ora è una richiesta di rete.

E le richieste di rete possono fallire.

Un servizio può andare in timeout. Un database può diventare temporaneamente irraggiungibile. Una richiesta può essere ritentata. Un servizio può rilasciare una modifica prima che un altro sia pronto a riceverla. All’improvviso ti ritrovi alle prese con problemi da sistemi distribuiti che, quando tutto viveva in un’unica applicazione, semplicemente non esistevano.

Il prodotto non è necessariamente diventato più complicato.

L’architettura sì.

Il costo nascosto di essere «scalabili»

Quando si parla di scalabilità, di solito si intende il traffico.

Il sistema regge dieci volte più utenti? Riesce a gestire più richieste? Una certa parte dell’applicazione si può scalare in modo indipendente?

Sono domande importanti, ma c’è un altro tipo di scalabilità che è facile trascurare: quanto bene il team riesce a capire e modificare il sistema.

Un sistema che regge milioni di richieste ma richiede tre giorni per essere capito prima di fare una piccola modifica non è proprio comodo da usare.

È uno dei motivi per cui il monolite modulare ha ricominciato a sembrare interessante.

Invece di spezzare subito tutto in servizi indipendenti, un team può tenere un’unica applicazione mantenendo comunque confini chiari al suo interno. Autenticazione, fatturazione, utenti, notifiche e gli altri domini possono avere i propri moduli e le proprie responsabilità, senza bisogno di un servizio e di un’infrastruttura separati per ciascuno.

Ottieni struttura senza pagare subito l’intero costo operativo dei sistemi distribuiti.

E se uno di quei moduli un giorno diventa abbastanza grande da giustificare un servizio separato, puoi estrarlo più avanti.

Questa flessibilità conta.

Provalo ora

Crea screenshot pronti per lo store in pochi minuti: gratis, senza filigrana sugli export.

Launch Shots è gratis per iniziare. Tutti i template (oltre 110), più di 220 cornici dei dispositivi e mockup 3D, localizzazione AI e caricamento diretto su App Store Connect e Google Play Console. Nessuna carta di credito richiesta.

Inizia gratis →

Non devi prevedere il futuro

Uno dei modi più facili per sovraingegnerizzare una startup è costruire attorno a problemi che non si sono ancora presentati.

«Potremmo avere milioni di utenti.»

«Potremmo avere più team di sviluppo.»

«Potremmo dover scalare questo componente in modo indipendente.»

«Potremmo cambiare database più avanti.»

Sono tutte cose possibili.

Ma possibile non vuol dire probabile, e probabile non vuol dire che devi risolverlo oggi.

L’architettura di una startup dovrebbe rispondere soprattutto ai problemi che il team sta vivendo davvero, non a una versione immaginaria dell’azienda fra cinque anni.

Se un giorno il sistema dovrà essere diviso, potrai dividerlo quando il motivo sarà chiaro.

Fino ad allora, tenere tutto insieme può rendere lo sviluppo più veloce, il debug più semplice e l’intero sistema più facile da capire.

Questo non significa ignorare la crescita futura.

Significa accettare che probabilmente non sai ancora come sarà esattamente quella crescita.

E va bene così.

Ogni servizio è una responsabilità in più

È facile guardare un’architettura a microservizi e vedere un insieme di pezzi piccoli e ben separati.

Quello che si trascura è che ognuno di quei pezzi ha un costo operativo.

Un servizio ha bisogno di deploy. Ha bisogno di monitoraggio. Ha bisogno di log. Ha bisogno di alert. Ha bisogno di configurazione. Qualcuno deve sapere cosa succede quando va giù. Qualcuno deve indagare quando la sua latenza all’improvviso aumenta.

Ora immagina di farlo per dieci servizi.

Poi venti.

Poi cinquanta.

Per una grande organizzazione questo overhead può valere assolutamente la pena. L’indipendenza tra team e sistemi può portare abbastanza valore da giustificare tutta quella complessità.

Per un team piccolo, invece, può diventare una distrazione.

Invece di dedicare tempo a migliorare il prodotto, gli sviluppatori possono finire per passarne una parte consistente a manutenere i meccanismi che servono a tenere in piedi l’architettura.

Ed è uno dei costi meno evidenti dei microservizi.

Il codice in sé potrebbe non essere particolarmente difficile.

È tutto quello che gli sta intorno a cominciare a pesare.

Il monolite modulare merita più rispetto

Il monolite modulare sta da qualche parte tra i due estremi.

È sempre un’unica applicazione, ma non deve per forza essere un’enorme codebase aggrovigliata in cui tutto può accedere a tutto.

L’applicazione può essere divisa in moduli logici con responsabilità e confini chiari.

Così gli sviluppatori possono ragionare per domini separati senza mettere un confine di rete tra un dominio e l’altro.

Anche lo sviluppo può restare relativamente semplice. Far girare l’applicazione in locale è più facile. Il debug è in genere più lineare. Le transazioni possono essere più facili da gestire. Il deploy non richiede di coordinare una serie di servizi indipendenti.

E c’è meno infrastruttura da mantenere.

Soprattutto, partire con un monolite non significa restarci bloccato per sempre.

Un monolite ben strutturato può addirittura rendere più facile un futuro passaggio ai microservizi, perché i confini esistono già.

Se un giorno il modulo di fatturazione diventa la parte del sistema che ha davvero bisogno di scalare o essere rilasciata in modo indipendente, puoi estrarlo.

Non devi estrarre tutto solo perché una parte deve cambiare.

È questo il vero vantaggio di progettare buoni confini.

Ti lasci delle opzioni aperte.

Quindi quando hanno davvero senso i microservizi?

Non esiste un numero magico di utenti oltre il quale un’azienda dovrebbe passare di colpo dal monolite ai microservizi.

Il traffico da solo non basta per prendere questa decisione.

I microservizi diventano molto più convincenti quando parti diverse del sistema hanno esigenze di scalabilità davvero diverse, quando i team devono rilasciare in modo indipendente, quando i confini tra domini sono ben compresi o quando certi componenti richiedono tecnologie o infrastrutture completamente diverse.

Conta anche la struttura del team.

Un’organizzazione con decine di team di sviluppo ha problemi di coordinamento molto diversi da una startup con quattro sviluppatori.

L’architettura dovrebbe rispondere a queste realtà.

Se separi un servizio perché un componente sta causando un vero problema di scalabilità, quello è un motivo.

Se separi un dominio perché più team devono lavorarci in modo indipendente, quello è un motivo.

Se lo fai perché «un giorno potrebbe servirci», forse conviene aspettare.

La scelta architetturale migliore spesso è quella che risolve il problema di oggi senza crearne cinque nuovi.

L’architettura più sofisticata potrebbe essere quella noiosa

L’ingegneria del software tende a premiare la complessità.

Un diagramma pieno di servizi, code, database, event bus e componenti infrastrutturali può fare un certo effetto.

Ma gli utenti non vedono niente di tutto questo.

Vedono se il prodotto si carica in fretta. Vedono se i loro dati sono al sicuro. Vedono se una funzionalità funziona quando ne hanno bisogno. Vedono se il prodotto sembra affidabile.

È questo che, alla fine, l’architettura deve sostenere.

A volte questo vuol dire microservizi.

A volte vuol dire un monolite modulare.

A volte vuol dire qualcosa nel mezzo.

L’errore è dare per scontato che un’architettura più complicata significhi automaticamente un team più maturo.

Una buona architettura non si misura da quante tecnologie riesci a infilare in un sistema.

Si misura dal costruire qualcosa di abbastanza facile da capire, abbastanza affidabile da gestire e abbastanza flessibile da cambiare quando cambia il prodotto.

Forse è per questo che alcuni team stanno tornando ai monoliti.

Non stanno necessariamente rinunciando alla scalabilità.

Si stanno rendendo conto che anche la semplicità è una forma di scalabilità, soprattutto quando quello che deve scalare non è solo l’infrastruttura, ma il team che costruisce il prodotto.