The Teaching Hub
DB: …

CQRS

Separa il modello di scrittura (comandi, invarianti forti) dal modello di lettura (query, viste denormalizzate, materialized views).

Approfondimento

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

Command Query Responsibility Segregation

CQRS separa il percorso di scrittura (comandi, invarianti forti, transazioni locali sul write model) dal percorso di lettura (query veloci su viste denormalizzate, cache, read model). Gli stessi fatti di dominio possono alimentare il read model in modo asincrono tramite eventi.

Non è obbligatorio avere database diversi: a volte basta uno schema dedicato o viste materializzate. La complessità cresce con il numero di proiezioni, la latenza accettabile e i tool di osservabilità.

Consistenza e UX

Dopo un comando, il read model può essere indietro di millisecondi o secondi: documenta SLI/ SLO di freschezza. In UI, mostra pending, conferma ottimistica con rollback guidato dagli eventi, o invalidazioni mirate.

Il write side espone errori di dominio chiari; il read side espone viste pensate per schermate e report, non per esporre direttamente le stesse tabelle transazionali.

Palcoscenico

Passo 1/5

Write model

Comandi e invarianti

Bus / outbox

Eventi verso projection

Read model

Viste veloci

Comando

Il client invia PlaceOrder: è un intento, non una vista.

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.order.command",
  "data": {
    "name": "PlaceOrder",
    "payload": { "customerId": "cus_1", "lines": [] }
  }
}

Lab: comando vs query (in memoria)

Il write model emette un evento; il read model è aggiornato da un handler separato (simula worker asincrono).

Caricamento playground…