f in x
Event Sourcing e CQRS — Perché i tuoi microservizi hanno bisogno di eventi immutabili
> cd .. / HUB_EDITORIALE > Visualizza in Inglese
Sviluppo di siti web

Event Sourcing e CQRS — Perché i tuoi microservizi hanno bisogno di eventi immutabili

[2026-07-07] Author: Ing. Calogero Bono
Zenithby Meteora Web Il sistema operativo della tua attività. Social, clienti, prenotazioni e fatture in un'unica piattaforma. Palestre, barber, professionisti. Scopri Zenith Demo gratis · senza carta

Il problema è vecchio come i database relazionali: aggiorni un record, perdi la storia. Un ordine cambia stato, un prezzo viene modificato, un cliente corregge l'indirizzo — e tu, senza un log granulare, non sai più cosa è successo. Nei microservizi, dove ogni servizio ha il suo dato, il caos è dietro l'angolo. Event sourcing e CQRS non sono mode: sono la risposta a decenni di compromessi. Noi ci siamo arrivati gestendo il sistema ERP di un negozio di abbigliamento: lì ogni movimento di magazzino era una riga, non un UPDATE. Lo stesso principio vale per software distribuiti.

Perché scegliere un'architettura event-driven invece del classico CRUD?

CRUD (Create, Read, Update, Delete) funziona finché un solo utente modifica un record. In un sistema distribuito, invece, più servizi devono reagire agli stessi cambiamenti. Con CRUD devi scrivere webhook, polling, code di job. Con event-driven ogni modifica è un evento pubblicato su un broker (Kafka, RabbitMQ, NATS). Ogni servizio interessato lo consuma indipendentemente. Zero polling, zero accoppiamento.

Noi, di Meteora Web, abbiamo costruito una piattaforma proprietaria per gestire la presenza social di più clienti. Quando un cliente cambiava il piano tariffario, un solo evento "PianoModificato" aggiornava il billing, il calendario editoriale e le notifiche. Con CRUD avremmo dovuto coordinare tre UPDATE in tre servizi diversi — un incubo di transazioni distribuite.

Sponsored Protocol

Cosa si guadagna in termini economici?

Meno codice di integrazione, meno bug, meno tempo perso a sincronizzare dati. Il costo di sviluppo iniziale è più alto, ma il TCO (Total Cost of Ownership) crolla quando il sistema scala. Veniamo dalla contabilità: lo stesso principio delle scritture contabili — ogni evento è una riga in partita doppia, immutabile, tracciabile.

Come funziona l'event sourcing e quali problemi risolve?

L'event sourcing capovolge la logica: invece di salvare lo stato attuale di un'entità, salvi la sequenza di eventi che l'hanno generata. Lo stato corrente è derivato riproducendo gli eventi. È come il libro giornale di un commercialista: ogni transazione è registrata, e il saldo finale si calcola rileggendo tutte le righe.

Esempio pratico: carrello e-commerce

// Evento salvato nell'event store
class ArticoloAggiunto {
    UUID carrelloId;
    UUID prodottoId;
    int quantità;
    LocalDateTime timestamp;
}

// Ricostruzione dello stato
Carrello carrello = eventStore
    .getEvents(carrelloId)
    .reduce(Carrello::applica, new Carrello());

Vantaggi immediati:

Sponsored Protocol

  • Audit trail completo: ogni cambiamento è tracciato, data, chi, cosa.
  • Time travel: puoi ricostruire lo stato a qualsiasi data — utile per debugging, report, ripristini.
  • Sincronizzazione tra servizi: ogni consumer riceve gli eventi nell'ordine corretto.

Uno svantaggio? La gestione dell'evoluzione degli eventi (versioning). Se modifichi la struttura di un evento, devi gestire più versioni. Noi lo abbiamo affrontato con un pattern semplice: ogni evento ha un campo version e un upcaster che lo trasforma.

CQRS: perché separare lettura e scrittura nei sistemi distribuiti?

CQRS (Command Query Responsibility Segregation) divide i modelli di comando (scrittura) e query (lettura). I comandi mutano lo stato, le query lo leggono. Sembra ovvio, ma nel CRUD classico usi lo stesso modello per entrambi — e quando le query diventano complesse, il modello di scrittura si appesantisce.

Con CQRS:

  • Modello di scrittura: ottimizzato per validazioni e regole di dominio. Aggregati piccoli, eventi immutabili.
  • Modello di lettura: denormalizzato, pronto per le UI. Può essere un database SQL ottimizzato per SELECT, un motore di ricerca, una cache Redis.

Un esempio reale: il sistema di gestione delle prenotazioni per un toelettatore. Le scritture (prenota, cancella, sposta) seguono regole rigide (non sovrapposizioni). Le letture (calendario del mese) devono essere velocissime. Con CQRS abbiamo separato le due cose: event store per i comandi, una tabella denormalizzata per le query. Il calendario si aggiorna in tempo reale e l'utente non vede mai dati sporchi.

Sponsored Protocol

CQRS senza event sourcing è possibile?

Sì, ma perdiamo l'audit trail. L'event sourcing è il modo più pulito per alimentare il modello di lettura: le proiezioni ascoltano gli eventi e aggiornano i database di query. In pratica, un binomio quasi obbligato quando serve consistenza eventuale e tracciabilità.

Come implementare event sourcing e CQRS insieme in un progetto reale?

La ricetta non è un framework magico, ma un insieme di scelte architetturali. Noi partiamo sempre da una domanda: “Il dominio ha bisogno di storia immutabile?” Se la risposta è sì, procediamo così:

1. Scegli l'event store

Puoi usare database specializzati (EventStoreDB) o implementare un layer sopra PostgreSQL (tabelle append-only). Noi preferiamo PostgreSQL per progetti piccoli/medi: una tabella events con colonne aggregate_id, version, event_type, data (JSONB).

CREATE TABLE events (
    id BIGSERIAL PRIMARY KEY,
    aggregate_id UUID NOT NULL,
    version INT NOT NULL,
    event_type VARCHAR(255) NOT NULL,
    data JSONB NOT NULL,
    created_at TIMESTAMPTZ DEFAULT NOW(),
    UNIQUE(aggregate_id, version)
);

2. Definisci comandi e handler

Un comando è un DTO (Data Transfer Object). L'handler carica l'aggregato dall'event store, applica la logica di dominio, produce nuovi eventi e li salva in una transazione.

Sponsored Protocol

class AggiungiArticoloHandler {
    public function __construct(
        private EventStore $eventStore,
        private EventBus $eventBus
    ) {}

    public function __invoke(AggiungiArticolo $command): void {
        $carrello = Carrello::ricostruisci(
            $this->eventStore->getEvents($command->carrelloId)
        );
        $eventi = $carrello->aggiungiArticolo($command->prodottoId, $command->quantità);
        $this->eventStore->append($command->carrelloId, $eventi);
        $this->eventBus->publish(...$eventi);
    }
}

3. Costruisci le proiezioni (modello di lettura)

Un consumer ascolta gli eventi e aggiorna una tabella denormalizzata. Per esempio, un ordine evaso aggiorna una vista “OrdiniRecentili”.

class OrdiniProiezione {
    public function onOrdineEvato(OrdineEvato $event): void {
        DB::table('vista_ordini')->updateOrInsert(
            ['ordine_id' => $event->ordineId],
            ['stato' => 'evaso', 'data_evasione' => $event->timestamp]
        );
    }
}

4. Gestisci la consistenza eventuale

Tra comando e query c'è un delay (di solito millisecondi). Se il tuo caso d'uso richiede consistenza immediata (es. prelievo contanti), CQRS non va bene. In tutti gli altri casi, funziona.

Sponsored Protocol

Cosa fare adesso

Hai tre azioni concrete da portare a casa:

  1. Analizza il tuo dominio: dove hai bisogno di audit trail? Dove le letture sono molto diverse dalle scritture? Quelli sono candidati ideali per event sourcing e CQRS.
  2. Fai un prototipo con PostgreSQL come event store: implementa una sola entità (es. ordine o carrello) con comandi, event store e una proiezione. Vedrai subito benefici.
  3. Non cadere nella trappola del “tutto CQRS”: non tutti i microservizi hanno bisogno di questa complessità. Isola i bounded context che ne traggono vantaggio.

Noi, di Meteora Web, usiamo questi pattern da anni nei progetti che sviluppiamo con Laravel e Livewire. Il nostro pillar su Microservizi e Architettura Distribuita ti dà il quadro completo. Se vuoi approfondire, leggi anche come la sicurezza si intreccia con gli eventi distribuiti.

Ing. Calogero Bono

> AUTHOR_EXTRACTED

Ing. Calogero Bono

Ingegnere informatico, fondatore di Meteora Web e Zenith OS. System administrator e progettista di piattaforme, app e CMS proprietari, con esperienza in sviluppo full-stack, marketing digitale ed ecosistema Google.
[ Read Full Dossier ]

> METEORA_WEB // WEB AGENCY

Costruiamo la presenza digitale che la tua azienda merita.

Siti web, social, pubblicità online, e-commerce e hosting performante: ingegnerizzati con metodo da ingegneri informatici a Sciacca, per tutta Italia.

> MW_JOURNAL

> READ_ALL()