Ogni volta che inizia un nuovo progetto, c'è un momento preciso in cui qualcuno in riunione dice: "Allora, come lo costruiamo?". È una domanda che sembra semplice. Non lo è.
Nel corso degli anni ho imparato che la scelta dell'architettura non è un problema tecnico — è un problema di contesto. Ho visto progetti partire con architetture sovradimensionate che hanno rallentato il team per mesi. E ho visto l'opposto: sistemi nati "semplici" che dopo un anno erano diventati un groviglio impossibile da scalare.
Questo articolo non è una guida su cosa siano i microservizi o il monolite. È il racconto di come ragiono io quando mi trovo davanti a quel foglio bianco.
Prima ancora di aprire un editor o disegnare un diagramma, faccio sempre una domanda al team (o a me stesso, se lavoro da solo):
"Tra 6 mesi, cosa deve essere vero di questo sistema?"
Sembra banale. Ma la risposta cambia tutto. Se mi dicono "deve essere live e funzionante", ragiono in un modo. Se mi dicono "deve gestire 10x il traffico attuale", ragiono in un altro. Se mi dicono "non lo sappiamo ancora", quella è già un'informazione preziosissima.
L'architettura deve servire gli obiettivi del progetto, non soddisfare la mia curiosità tecnologica. Ho fatto questo errore una volta — ho proposto un'architettura a microservizi per un progetto interno che aveva un team di due persone. Tre mesi dopo, stavo ancora configurando l'orchestrazione dei container mentre il prodotto non era ancora live. Lezione imparata.
Dopo anni di progetti, ho distillato il mio processo in quattro domande. Le faccio sempre in questo ordine.
Se il dominio applicativo è chiaro, stabile e ben compreso — un gestionale, un'area riservata, un sistema di prenotazioni — posso permettermi di pensare a una struttura più articolata fin dall'inizio.
Se invece siamo in una fase esplorativa, dove i requisiti cambiano ogni settimana e il business sta ancora capendo cosa vuole, parto sempre da qualcosa di semplice e modulare. In questi casi, l'architettura giusta è quella che puoi cambiare. Un buon monolite ben strutturato, con confini logici chiari tra i moduli, batte qualsiasi sistema distribuito in termini di velocità di iterazione.
Questa è forse la variabile più sottovalutata. L'architettura non è solo codice — è anche struttura organizzativa.
Un team di due-tre persone che lavora in modo sincrono non ha bisogno di microservizi. Ha bisogno di muoversi veloce, fare deploy frequenti e non perdere tempo in overhead di comunicazione tra servizi. Un team di dieci persone diviso in sotto-team che lavorano su domini diversi, invece, potrebbe beneficiare di confini netti tra i componenti — proprio per evitare che si pestino i piedi a vicenda.
Ho sempre in mente la Legge di Conway: i sistemi che costruiamo tendono a rispecchiare la struttura di comunicazione del team che li costruisce. Meglio usarla a proprio vantaggio che combatterla.
Qui il dialogo con il cliente o il product owner diventa fondamentale. Spesso sento dire: "deve scalare", "deve essere velocissimo", "deve essere sempre disponibile". Queste sono aspirazioni, non requisiti.
Quando approfondisco, scopro che:
Conoscere i numeri reali mi permette di non over-engineering. Non ho bisogno di Kafka se devo gestire 50 eventi al minuto. Non ho bisogno di un sistema di caching distribuito se il database risponde in 20ms e le query sono già ottimizzate.
Il lancio non è la fine — è l'inizio. Mi chiedo sempre: chi farà manutenzione? Il team attuale, un altro team, il cliente stesso? Quante modifiche sono previste dopo il go-live?
Se so che dopo il lancio il progetto entrerà in una fase di manutenzione con poca evoluzione, posso accettare qualche compromesso strutturale. Se invece è un prodotto vivo che crescerà, investo di più nella qualità architetturale fin dall'inizio — anche se costa tempo adesso.
Dopo aver risposto a queste quattro domande, ho un punto di partenza quasi sempre uguale: un'architettura modulare a livelli, deployata come singola unità.
In pratica: backend con separazione netta tra layer (presentazione, business logic, accesso ai dati), frontend disaccoppiato che comunica via API, database relazionale come prima scelta salvo ragioni concrete per andare altrove.
È l'architettura meno glamour del mondo. Non fa colpo nelle presentazioni. Ma funziona, è comprensibile da chiunque entri nel team, ed è modificabile.
Da lì in poi, evolvo solo quando ho un problema reale da risolvere — non un problema ipotetico. Se una parte del sistema diventa un collo di bottiglia, la isolo. Se un dominio cresce fino a richiedere un team dedicato, lo estraggo. Ma non prima.
Ho smesso di disegnare l'architettura finale prima di scrivere una riga di codice.
Adesso dedico le prime settimane a costruire un vertical slice — una fetta verticale del sistema che attraversa tutti i layer, dalla UI al database, su un caso d'uso reale. Questo mi dice più cose sull'architettura giusta di qualsiasi sessione di design teorica.
I problemi veri emergono quando il codice incontra la realtà: la struttura dei dati che non torna, l'integrazione con un'API esterna che si comporta diversamente dalla documentazione, il requisito che sembrava semplice e invece nasconde complessità. Meglio scoprirlo presto, con poco codice scritto, che tardi.
Non esiste l'architettura giusta in assoluto. Esiste l'architettura giusta per quel progetto, in quel momento, con quel team.
Il mio processo si riduce a questo: capire il contesto prima di aprire qualsiasi strumento, partire semplice, evolvere quando necessario. Ogni volta che ho deviato da questo principio per seguire una tecnologia interessante o un pattern di moda, me ne sono pentito.