Vai al contenuto principale
Categorie articolo: Code

DDD, microservizi e architetture evolutive: Event Sourcing is not Event Streaming

23 Giugno 2025 - 4 minuti di lettura

L’ultima volta ci siamo lasciati sul tema della sostenibilità architetturale.

In questo nono e penultimo capitolo della saga sul DDD, che prende spunto da un mio articolo pubblicato nella rivista web MokaByte, vi parlerò di due concetti noti ma che capita di confondere tra loro: Event Sourcing ed Event Streaming.

Le parole sono importanti

Nel mondo dello sviluppo software, alcuni termini di tendenza possono generare confusione, soprattutto quando sembrano simili ma indicano concetti distinti. Un esempio? Event Sourcing ed Event Streaming: entrambi svolgono un ruolo chiave nelle architetture moderne, ma rispondono a esigenze diverse e si applicano in contesti separati.

Event Sourcing

Event Sourcing è un modello architetturale in cui ogni cambiamento di stato di un sistema, in particolare di un aggregato usando il gergo del mondo Domain-Driven Design, viene rappresentato come un evento immutabile e memorizzato in ordine cronologico. Questo approccio permette di ricostruire lo stato del sistema in qualsiasi momento, semplicemente rileggendo gli eventi.

Un database progettato per questa architettura deve supportare la concorrenza ottimistica. In pratica, consente sempre la lettura degli eventi, mentre impone vincoli solo durante la fase di aggiornamento. Poiché ogni evento rappresenta un fatto già accaduto e non modificabile, l’unico controllo si applica quando si prova ad aggiungere (append) un nuovo evento.

Ogni Event Store assegna un numero di versione, o progressivo, a ciascun evento. Se due operazioni tentano di scrivere simultaneamente sullo stesso stream dello stesso aggregato, il sistema verifica la versione. Solo se la versione dell’aggregato corrisponde all’ultima versione dello stream, l’evento viene salvato e la versione viene aggiornata. Altrimenti, la scrittura viene respinta.

Questa meccanica è essenziale per garantire la Strong Consistency dell’aggregato. In un’architettura a eventi, la Eventual Consistency si applica ai modelli di lettura — come previsto dal modello CQRS+ES — mentre la Strong Consistency riguarda il modello di scrittura.

In sintesi, un Event Store deve:

  • garantire una cronologia completa delle modifiche di stato, utile per funzionalità come audit e analisi retrospettiva;
  • memorizzare una sequenza immutabile di eventi.

Un database Event Store è il partner ideale in un’architettura CQRS in cui si desidera salvare i Domain Event, ovvero gli eventi che descrivono il comportamento del sistema, per ricostruire lo stato degli aggregati.

Un esempio concreto è un sistema e-commerce. In questo contesto, Event Sourcing può tracciare eventi come “OrdineDaCarrelloCreato”, “PagamentoTramiteCartaDiCreditoConfermato” o “OrdineConPrioritàAltaSpedito”. Ciò consente non solo di ricostruire la cronologia completa di un ordine, ma anche di comprendere a fondo il processo di business. Per questo motivo, l’Event Store rappresenta la source-of-truth del sistema.

Event Sourcing
Event Sourcing

Event Streaming

Il secondo protagonista di questo confronto è l’Event Streaming. Si tratta di un paradigma orientato allo spostamento in tempo reale di informazioni — in pratica, dati — da un punto all’altro di un sistema distribuito. Tra gli strumenti più comuni che lo implementano troviamo Kafka, RabbitMQ, Azure Service Bus, AWS SQS e SNS.

Ogni componente di un sistema distribuito può sottoscriversi a questi flussi per ricevere dati in tempo reale. Questi dati attivano azioni diverse, come aggiornamenti su database, attivazione di dispositivi IoT o transazioni finanziarie in una piattaforma bancaria.

I sistemi di Event Streaming non sono pensati per sostituire un database. Pur disponendo di funzionalità di storage, queste servono a garantire resilienza e tolleranza ai guasti. Non sono progettate per l’uso tipico di un database relazionale. Grazie a queste caratteristiche, il sistema riesce a gestire correttamente situazioni in cui, ad esempio, il broker interrompe il servizio o il sistema destinatario non è temporaneamente disponibile.

È vero che anche questi sistemi mantengono un log append-only, proprio come un Event Store. Tuttavia, gli eventi che contengono non possono essere considerati una source-of-truth del sistema. Almeno, non nello stesso modo in cui lo è un Event Store.

Event Streaming
Event Streaming

Confronto

Gli eventi possono essere considerati una source-of-truth solo se usati nel modello di scrittura per ricostruire lo stato di un aggregato. Quando gli eventi servono a costruire una vista, la verità viene delegata a uno storage esterno. In questo modo si introduce il rischio che altri stream aggiornino lo stesso storage, compromettendo la coerenza dei fatti registrati per quell’aggregato. Utilizzare strumenti di Event Streaming come se fossero sistemi di Event Sourcing porta esattamente a questo problema.

Un ulteriore punto critico riguarda la lunghezza degli stream. In Kafka, ad esempio, la quantità di eventi in un Topic non influisce sulle prestazioni: il Topic è un canale di comunicazione, non un archivio persistente. In un Event Store, invece, ogni stream rappresenta una porzione di database. Più eventi contiene, maggiore sarà il suo peso, con un impatto diretto sulle prestazioni complessive. Inoltre, stream troppo lunghi rendono più complesso il versionamento degli eventi — un aspetto fondamentale nel modello CQRS+ES, ma che va oltre gli obiettivi di questo articolo.

Conclusioni

È facile lasciarsi tentare dall’idea di usare un sistema di Event Streaming come soluzione tuttofare. Le sue promesse possono sembrare vantaggiose, ma nel tempo rischiano di generare più problemi che benefici. Lo sviluppo di soluzioni software non è una questione di eleganza tecnica: si tratta, prima di tutto, di risolvere problemi di business.

Poiché i problemi di business cambiano costantemente, anche i nostri sistemi devono evolvere. Per questo motivo, è fondamentale usare ogni strumento per lo scopo per cui è stato progettato. Così facendo, sarà più semplice eliminare parte della complessità accidentale che spesso rallenta lo sviluppo e rende più fragile l’architettura.

Nell’ultimo articolo vi parlerò della figura del Software Architect e dell’importanza di questo ruolo.

Articolo scritto da