Prima o poi, in ogni startup arriva quel momento. Di solito parte tutto dallo sviluppatore più carico del gruppo: "Dobbiamo passare ai microservizi. Il monolite non scala! Guarda Netflix, loro sì che lo fanno. Dobbiamo pensare in grande." E così, senza accorgersene, il team si lancia in una migrazione che dura mesi, non risolve i veri problemi, e ne tira fuori di nuovi.
Se il tuo prodotto va bene così com’è, monolitico, cioè raccolto in un’unica applicazione, forse conviene lasciarlo stare. Non è che i microservizi, cioè tanti servizi separati che collaborano tra loro, siano sbagliati: semplicemente risolvono problemi che probabilmente tu non hai.
Il vero problema che risolvono i microservizi
I microservizi risolvono diversi problemi tecnici reali, ma nella pratica diventano davvero utili soprattutto quando la complessità organizzativa del team cresce molto.
In organizzazioni molto grandi, come Netflix, Amazon o Google, se tutti lavorano sullo stesso prodotto, il monolite diventa una gabbia. Ogni rilascio richiede che i team si parlino, si sincronizzino. Se c’è un bug da una parte, blocca tutto il resto. Le riunioni di allineamento portano via più tempo dello sviluppo.
Qui i microservizi funzionano: ogni team ha il suo servizio, lo rilascia quando vuole, e parla con gli altri solo tramite API chiare. Certo, il prezzo è la complessità tecnica di gestire tanti servizi. Il vantaggio? Ogni team può andare per conto suo.
Se il team è piccolo e ben coordinato, spesso questo problema è molto meno rilevante. Bastano due parole a voce e si risolve tutto, i deploy sono semplici, e tutta la fatica aggiuntiva dei microservizi non porta nessun beneficio vero.
Cosa succede davvero quando ti butti sui microservizi troppo presto
La complessità operativa schizza alle stelle
Un monolite? È un processo, un database, un deploy e via. Con i microservizi ti ritrovi con decine di processi, spesso anche più database, mille pipeline di deploy, e una rete di servizi da tenere in piedi.
All’improvviso ti servono service discovery, cioè meccanismi per far sì che i servizi si trovino tra loro, bilanciamento del carico, circuit breaker per i guasti, tracing distribuito per seguire una richiesta che passa da cinque servizi diversi, logging centralizzato per raccogliere i log da ogni dove. E qualcuno deve pure occuparsene, ogni giorno.
Così il tuo team di cinque persone, che prima lavorava solo sulle funzionalità, ora passa quasi metà del tempo a tenere in piedi l’infrastruttura. Rischi di ridurre sensibilmente la velocità di sviluppo per inseguire un problema che non avevi.
Il debugging diventa un incubo
Nel monolite, quando qualcosa va storto, hai uno stack trace. Lo leggi, capisci dov’è il guaio, lo sistemi.
Nei microservizi, la stessa richiesta dell’utente viaggia tra quattro servizi diversi. L’errore può essere ovunque: in uno dei servizi, nella comunicazione tra loro, nel message broker, in un timeout di rete, o in una race condition che si mostra solo se le risposte arrivano in un certo ordine.
Risultato? Risolvere un bug in un sistema distribuito può richiedere molto più tempo rispetto a un monolite. Se sei un team piccolo, questa cosa ti spezza.
La gestione della coerenza dei dati diventa molto più complessa
Nel monolite hai una transazione bella pulita. Inizi, fai le operazioni, commit o rollback. I dati restano sempre a posto.
Nei microservizi, ogni servizio si tiene il suo database. Se devi fare un’operazione che coinvolge due servizi, entri nel magico mondo della consistenza eventuale — saga, outbox, compensazione. Devi gestire il caso in cui il primo servizio va, il secondo no. E nel frattempo, cosa mostri all’utente?
Non è impossibile, per carità. Solo che ora ti ritrovi con una complessità vera, che prima non avevi. Devi progettarla, implementarla, testarla, mantenerla. E questo vale per ogni singola operazione che passa tra più servizi.
"Ma il monolite non scala!"
Questa è un’idea molto diffusa, ma spesso imprecisa.
Un monolite scritto bene scala eccome. Puoi aumentare la potenza del server (scaling verticale) o aggiungere più istanze dietro a un load balancer (scaling orizzontale), senza grossi drammi. Laravel, Rails e Django possono gestire carichi molto elevati su infrastrutture moderne, se configurati e ottimizzati correttamente.
E sai quante richieste al secondo riceve davvero il tuo prodotto? Se non hai idea, di solito sono molte meno di quello che pensi. Nella pratica, molte web app ricevono un carico molto inferiore a quello che si immagina: un server solo le regge senza problemi — basta che il database sia ottimizzato.
Molto spesso il vero collo di bottiglia è proprio il database. Query lente, N+1 che non vedi, indici che mancano. Questi problemi ce li hai sia nei monoliti che nei microservizi — anzi, con i microservizi te li ritrovi moltiplicati, uno per ogni servizio.
Quando i microservizi hanno davvero senso
I microservizi non sono il male. Hanno senso in situazioni molto specifiche. Per esempio quando hai un team davvero numeroso e la coordinazione diventa un problema concreto, al punto che per fare un deploy servono settimane di sincronizzazione. Oppure quando hai componenti che devono scalare in modo molto diverso, come un servizio che elabora video e richiede cento istanze mentre il resto dell’app ne usa due. O ancora quando esistono esigenze tecniche reali che impongono stack diversi, per esempio machine learning in Python e il resto del sistema in PHP.
Tutte queste sono sfide che in genere arrivano dopo che il prodotto ha avuto successo, non prima. Pensare ai microservizi fin dall’inizio è come comprare un autobus perché “magari un giorno avremo più passeggeri”. Per adesso sei da solo sull’autobus e il parcheggio ti costa un occhio.
Cosa fare invece dei microservizi
Quando il monolite inizia a diventare difficile da gestire, quasi sempre la soluzione non è spacchettarlo. Di solito basta organizzarlo meglio. Conviene definire con chiarezza i moduli per domini di business, con confini leggibili; in Laravel puoi usare directory per dominio, in Symfony bounded contexts. Tutto resta nello stesso deploy, ma il codice smette di essere indistinto.
Aiuta anche far comunicare i moduli tramite API interne e interfacce, invece di lasciare import casuali ovunque. Così, se un giorno servirà davvero estrarre un servizio, il confine sarà già pronto. Prima ancora di discutere architettura, poi, bisogna guardare al database: spesso i problemi di scalabilità stanno lì, nelle query. E se il problema è la paura del deploy, conviene investire in CI/CD, test automatici e rilasci frequenti, non in un’architettura che moltiplica i punti di rottura.
Per chi decide
Se nel tuo team qualcuno propone di passare ai microservizi, le domande da fare sono poche ma precise. Qual è il problema concreto che vogliamo risolvere? Se la risposta resta vaga, con parole come “scalabilità” o “modernizzazione”, è già un campanello d’allarme. Abbiamo davvero le competenze necessarie? Servono skill di DevOps, Kubernetes, networking e monitoring distribuito. E quanto ci costa questa migrazione in termini reali? Le stime su questi passaggi tendono a essere fortemente sottovalutate. Infine, la domanda più importante: esiste una soluzione più semplice? Molto spesso sì.
Un buon monolite è un vantaggio competitivo
Nel 2026, con l'AI che accelera lo sviluppo, un monolite ben strutturato fa la differenza. Una codebase unica e coerente tende a essere più semplice da navigare anche per gli strumenti AI, con relazioni tra moduli chiare, debug lineare. Invece, su un sistema distribuito, l’AI deve rincorrere servizi, interpretare protocolli, gestire stati sparsi ovunque.
La semplicità è una feature, prima ancora che una pecca. E nel software, le feature che ti fanno dormire sereno sono sempre quelle sottovalutate.
Simone Giusti
Consulente software strategico



