The Teaching Hub
DB: …

Event Sourcing

La verità è la sequenza append-only di eventi; lo stato è una riduzione (o snapshot + replay). Audit e temporal queries diventano naturali.

Approfondimento

Definizioni, contesto e collegamenti tra concetti — leggi prima del palcoscenico interattivo se parti da zero.

Stream append-only e proiezione

Event Sourcing memorizza la storia come sequenza immutabile di eventi di dominio. Lo “stato corrente” è una riduzione (fold) degli eventi, eventualmente accelerata da snapshot che catturano un checkpoint.

Ottiene audit naturale, temporal queries e replay per test di regressione sul dominio. Paghi in complessità: migrazioni degli eventi storici, gestione degli schemi, tool di ispezione e training del team.

Quando evitarlo

Se ti basta una tabella con CRUD e un audit log append-only per compliance, spesso spendi meno e vai più veloce. ES ha senso quando il dominio è event-first, servono ricostruzioni storiche affidabili o integrazioni multiple sulla stessa timeline.

Gli snapshot riducono il replay lungo; le funzioni di proiezione vanno versionate con cura quando cambi la semantica di eventi legacy, altrimenti ricostruisci stati sbagliati.

Concurrency control sullo stream

L’append usa spesso `expectedVersion` (o equivalente) per evitare write concorrenti sullo stesso aggregato: se la versione non combacia, rifiuti e chiedi al chiamante di ricaricare e riprovare — è lo stesso spirito dell’optimistic locking sulle righe SQL.

In lettura, separa stream tecnico da eventi di dominio esposti: gli strumenti admin possono mostrare la timeline grezza, mentre i servizi applicano solo ciò che il contratto consente.

Palcoscenico

Append-only stream (semplificato)

  • + FundsReserved

Contratto e codice

Schema JSON basato su CloudEvents 1.0, poi snippet server e client.

{
  "specversion": "1.0",
  "source": "/orders-service",
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "time": "2026-05-13T12:00:00.000Z",
  "datacontenttype": "application/json",
  "type": "com.example.ledger.append",
  "data": {
    "streamId": "acc_7712",
    "expectedVersion": 12,
    "events": [
      { "type": "FundsReserved", "payload": { "amount": 5000 } },
      { "type": "FundsCaptured", "payload": { "amount": 5000 } }
    ]
  }
}

Lab: fold degli eventi → stato

La funzione <code>reduce</code> è la proiezione: in produzione versionala quando cambi la semantica degli eventi legacy.

Caricamento playground…