Costruire Microservizi Scalabili: Pattern Reali dal Campo
Ingegneria Architettura 15 dicembre 2025

Costruire Microservizi Scalabili: Pattern Reali dal Campo

Uno sguardo pratico all'architettura microservizi - i pattern che funzionano davvero, le trappole che ci hanno morso, e perchรฉ a volte un monolite non รจ poi cosรฌ male.

E
Engineering Team
Senior Solutions Architects
14 min di lettura

Il Problema Reale

Quando abbiamo guardato per la prima volta questa piattaforma di servizi finanziari, aveva quell'odore familiare. Un monolite che serviva 50.000 utenti giornalieri, deployment che richiedevano finestre di manutenzione notturne, e un codebase dove toccare il modulo A in qualche modo rompeva il modulo Z.

Il business voleva costi di infrastruttura piรน bassi, piรน flessibilitร  di sviluppo, time-to-market piรน veloce, e la capacitร  di scalare feature individuali indipendentemente. Classico - ma il diavolo sta nei dettagli.

Microservizi: Hype vs Realtร 

Siamo onesti - i microservizi risolvono problemi specifici, non tutti i problemi. Ecco cosa ha davvero guidato la nostra decisione:

  • Indipendenza di deployment - rilasciare il modulo pagamenti senza toccare l'auth utente
  • Contenimento del blast radius - quando (non se) le cose si rompono, si rompono in piccolo
  • Persistenza poliglotta - usare Postgres per transazioni, Redis per sessioni, MongoDB per documenti
  • Ownership del team - confini chiari significano responsabilitร  chiara
  • Scaling mirato - scalare il servizio di ricerca durante i picchi, non tutta l'app

Deep Dive Architetturale

Abbiamo costruito sul Domain-Driven Design, ma non la versione accademica. I bounded context sono emersi da vere conversazioni di team, non da esercizi alla lavagna. I nostri principi:

  • I confini degli aggregati definiscono i confini dei servizi - se รจ una transazione, รจ un servizio
  • Eventi invece di chiamate sincrone - la coreografia batte l'orchestrazione nella maggior parte dei casi
  • Contratti API come cittadini di prima classe - rompi il contratto, rompi il build
  • Architettura shared-nothing - ogni servizio possiede i suoi dati, punto
  • L'osservabilitร  non รจ opzionale - se non puoi tracciarlo, non rilasciarlo

Lo Stack (E Perchรฉ)

Ogni scelta di tool era un tradeoff. Ecco dove siamo atterrati:

text
Infrastructure:
โ”œโ”€โ”€ Kubernetes (EKS) โ†’ Deployment dichiarativi, self-healing
โ”œโ”€โ”€ Istio service mesh โ†’ mTLS, traffic shaping, circuit breaking
โ”œโ”€โ”€ Kong API Gateway โ†’ Rate limiting, auth, trasformazione richieste
โ”‚
Messaging:
โ”œโ”€โ”€ Kafka โ†’ Event backbone, retention 7 giorni
โ”œโ”€โ”€ Redis Streams โ†’ Pub/sub leggero, dati effimeri
โ”‚
Data Layer:
โ”œโ”€โ”€ PostgreSQL โ†’ Transazioni ACID, JSONB per flessibilitร 
โ”œโ”€โ”€ MongoDB โ†’ Document store per audit log, activity feed
โ”œโ”€โ”€ Redis Cluster โ†’ Session store, caching distribuito
โ”œโ”€โ”€ Elasticsearch โ†’ Ricerca full-text, aggregazione log
โ”‚
Observability:
โ”œโ”€โ”€ OpenTelemetry โ†’ Instrumentazione vendor-agnostica
โ”œโ”€โ”€ Prometheus + Thanos โ†’ Metriche con storage a lungo termine
โ”œโ”€โ”€ Grafana โ†’ Dashboard, alerting
โ”œโ”€โ”€ Jaeger โ†’ Distributed tracing
โ”‚
CI/CD:
โ”œโ”€โ”€ GitLab CI โ†’ Build, test, security scanning
โ”œโ”€โ”€ ArgoCD โ†’ GitOps deployment
โ”œโ”€โ”€ Sealed Secrets โ†’ Gestione secret nativa K8s

Pattern Che Ci Hanno Salvato

La teoria va bene. Ecco cosa ci ha davvero tenuto fuori dai guai:

**Transactional Outbox** - Invece di dual-write (database + message broker), scriviamo gli eventi in una tabella outbox nella stessa transazione. Un processo separato li pubblica. Atomico. Affidabile. Niente incubi di transazioni distribuite.

**Event Sourcing (dove conta)** - Per i flussi di pagamento e i percorsi critici di audit, memorizziamo eventi, non stato. Ogni mutazione รจ un evento immutabile. Debuggare problemi di produzione riproducendo sequenze esatte. I team compliance lo adorano.

**CQRS con Proiezioni** - Modelli di scrittura ottimizzati per validazione, modelli di lettura ottimizzati per query. L'eventual consistency va bene per le viste di lettura. Il team reporting ottiene le sue tabelle denormalizzate senza inquinare il write path.

**Saga Orchestration** - Processi business di lunga durata (onboarding, settlement pagamenti) come macchine a stati esplicite. Transazioni compensative in caso di fallimento. Niente stati parziali orfani.

**Circuit Breaker + Bulkhead** - Hystrix รจ morto, ma i pattern no. Resilience4j gestisce circuit breaking, rate limiting e retry con backoff. Thread pool separati per integrazioni esterne.

Il Flusso di Pagamento: Architettura Reale

Ecco come il denaro reale si muove attraverso il sistema:

text
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”      โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”      โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚ API Gateway โ”‚โ”€โ”€โ”€โ”€โ”€โ”€โ”‚  Payment    โ”‚โ”€โ”€โ”€โ”€โ”€โ”€โ”‚   Fraud     โ”‚
โ”‚   (Kong)    โ”‚ gRPC โ”‚  Service    โ”‚ Eventโ”‚  Detection  โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜      โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”˜      โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                            โ”‚                    โ”‚
                     PaymentInitiated      FraudCheckCompleted
                            โ”‚                    โ”‚
                            โ–ผ                    โ–ผ
                     โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”      โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
                     โ”‚   Outbox    โ”‚      โ”‚    Risk     โ”‚
                     โ”‚   Table     โ”‚      โ”‚   Scoring   โ”‚
                     โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”˜      โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                            โ”‚                    โ”‚
                     Debezium CDC           RiskAssessed
                            โ”‚                    โ”‚
                            โ–ผ                    โ–ผ
                     โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
                     โ”‚         Kafka Topics            โ”‚
                     โ”‚  payments.initiated             โ”‚
                     โ”‚  fraud.checked                  โ”‚
                     โ”‚  risk.assessed                  โ”‚
                     โ”‚  payments.completed             โ”‚
                     โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                                    โ”‚
            โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
            โ–ผ                       โ–ผ                       โ–ผ
     โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”         โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”         โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
     โ”‚   Ledger    โ”‚         โ”‚   Order     โ”‚         โ”‚Notification โ”‚
     โ”‚   Service   โ”‚         โ”‚   Service   โ”‚         โ”‚   Service   โ”‚
     โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜         โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜         โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Strategia di Testing Che Funziona Davvero

Dimentica la piramide dei test per un momento. Nei sistemi distribuiti hai bisogno di:

  • Contract test (Pact) - I servizi parlano con stub, non dipendenze reali. I contratti si rompono in CI, non in produzione
  • Consumer-driven contract - I consumer definiscono cosa hanno bisogno, i provider provano che lo forniscono
  • Chaos testing (Chaos Monkey, Litmus) - Uccidere pod a caso. Iniettare latenza. Provare la resilienza
  • Synthetic monitoring - Sonde di produzione continue per i journey utente critici
  • Load testing come validazione - Abbiamo validato che l'architettura poteva gestire 80x il traffico originale attraverso rigorosi load test prima del lancio
  • Canary deployment - 1% del traffico alle nuove versioni, rollback automatico in caso di picco di errori

Cosa รˆ Realmente Successo

All'inizio, ci siamo concentrati sulla decomposizione del monolite - identificando le giunture, strangolando il vecchio sistema servizio per servizio. All'inizio รจ stato difficile. Le competenze di debugging distribuito mancavano, le trace erano incomplete, e le partizioni di rete esponevano bug di consistenza.

Dopo alcuni mesi, le cose hanno fatto click. I team possedevano i loro servizi end-to-end. I deployment sono diventati non-eventi. Il team di platform engineering aveva costruito abbastanza golden path per cui mettere su un nuovo servizio richiedeva ore, non settimane.

Quando il tempo รจ passato e l'architettura รจ maturata, i risultati hanno parlato da soli:

  • I tempi di risposta sono scesi da 850ms p99 a meno di 120ms p99
  • Zero-downtime deployment - le finestre di manutenzione sono diventate un ricordo
  • Costi di infrastruttura ridotti del 35% nonostante traffico piรน alto
  • Frequenza di deployment: da mensile a 50+ deploy giornalieri
  • Tempo medio di recupero: meno di 5 minuti per la maggior parte degli incidenti

Le Lezioni Difficili

Non tutto รจ andato liscio. Ecco cosa ha fatto male:

**L'eventual consistency รจ una feature, non un bug** - Ma spiegalo al PM che si chiede perchรฉ la dashboard mostra dati obsoleti. Progetta per questo. Comunicalo.

**Distributed tracing o morte** - Senza correlation ID e corretta propagazione del trace context, il debugging รจ archeologia. L'auto-instrumentazione di OpenTelemetry รจ tua amica.

**L'evoluzione dello schema รจ difficile** - Avro con schema registry. Solo modifiche backwards-compatible. I breaking change richiedono un nuovo topic.

**Kubernetes รจ un sistema operativo** - Non combatterlo. Imparalo. Resource limit, liveness probe, pod disruption budget - esistono per motivi.

**Il team platform non รจ negoziabile** - Qualcuno deve possedere le astrazioni di infrastruttura. Altrimenti, ogni team reinventa la ruota.

Quando NON Fare Microservizi

Parliamo chiaro - i microservizi sono costosi. Considera alternative se:

  • Il tuo team รจ piccolo - l'overhead di coordinamento ucciderร  la velocitร 
  • I confini del dominio non sono chiari - li disegnerai sbagliati e soffrirai dolori di migrazione
  • Non hai capacitร  di platform engineering - la complessitร  dell'infrastruttura esplode
  • I requisiti di latenza sono estremi - gli hop di rete si sommano
  • Il tuo monolite ha solo bisogno di migliore modularizzazione - prova prima un monolite modulare

Conclusioni

Alla fine di questo viaggio, avevamo una piattaforma che deployava continuamente, scalava su richiesta, e dava ai team vera ownership. Il business ha ottenuto quello che chiedeva: costi piรน bassi, delivery piรน veloce, e la flessibilitร  di evolvere.

Ne รจ valsa la pena? Per questa scala e questi requisiti, assolutamente. Ma abbiamo iniziato con un monolite modulare e abbiamo estratto servizi solo quando il dolore era reale.

Stai pensando a questo tipo di trasformazione? Inizia dal problema, non dalla soluzione.

Key Takeaways

L'architettura microservizi non riguarda seguire i trend - riguarda risolvere sfide specifiche di scaling e organizzazione. I pattern che abbiamo coperto (transactional outbox, event sourcing, CQRS, saga orchestration) non sono esercizi teorici; sono soluzioni testate in battaglia per veri problemi di sistemi distribuiti.

Abbiamo validato che l'architettura poteva sostenere 80x il traffico originale attraverso load testing completo. I deployment sono passati da eventi mensili a non-eventi che accadono dozzine di volte al giorno. Questo รจ il ritorno quando fai bene i fondamentali.

Hai sfide di architettura con cui stai lottando? Parliamo di pattern.

#microservices #kubernetes #docker #scalability #devops #cloud-native #event-sourcing #cqrs #ddd
E

Engineering Team

Senior Solutions Architects

Costruiamo sistemi distribuiti da prima che 'microservizi' fosse un termine. Le nostre cicatrici raccontano storie.