Event-driven architecture: introduzione pratica 🌩️
EDA non è una silver bullet. È più un coltellino svizzero: utilissimo, ma se lo usi come martello ti fai male.
L’Event-driven architecture (EDA) è un modo di progettare sistemi in cui i componenti non si chiamano direttamente (HTTP/gRPC “a catena”), ma comunicano tramite eventi pubblicati su un broker (o event stream). I consumer reagiscono agli eventi in modo asincrono.
Cos’è un evento (e cosa non è) 🧠
Un evento è un fatto accaduto nel dominio: qualcosa che è già successo e non lo “annulli” cambiandogli il nome.
- Evento:
OrdineCreato,PagamentoAutorizzato,UtenteRegistrato. - Non-evento (di solito):
AggiornaTabellaUtenti,RicalcolaReport(sono più comandi).
Eventi vs comandi 🎯
La distinzione sembra banale finché non ti ritrovi a pubblicare eventi che in realtà sono comandi mascherati. La regola mentale utile è: il comando chiede un’azione e si aspetta un esito; l’evento racconta un fatto già avvenuto e non “negozia”.
- Comando: “fai questa cosa” (intento, imperativo, spesso richiede risposta).
- Evento: “è successa questa cosa” (notifica, informativo, può avere molti consumer).
Nella pratica: i comandi sono utili dentro un bounded context; gli eventi sono ciò che condividi tra contesti (con molta disciplina).
Come trovi gli eventi (senza tirare a indovinare) 🧩
Se stai “inventando” i nomi evento davanti a un IDE, sei già sulla strada per UserUpdated e parenti stretti.
Un approccio pragmatico è partire dal comportamento di business: workshop tipo EventStorming aiutano a far emergere fatti (eventi), intenti (comandi) e confini (aggregati/bounded context) con le persone giuste al tavolo.
I tre blocchi base: Producer → Broker → Consumer 🧱
flowchart LR
U[Utente] --> API[API / Applicazione]
API -->|pubblica evento| B[(Broker / Stream)]
B --> C1[Consumer: Email]
B --> C2[Consumer: Analytics]
B --> C3[Consumer: Inventory]
- Producer: pubblica eventi quando accade qualcosa di rilevante.
- Broker / Event channel: riceve, conserva (a seconda della tecnologia) e distribuisce.
- Consumer: reagisce agli eventi, indipendentemente e spesso in parallelo.
Risultato: l’utente non aspetta più tutte le “side effects” (email, analytics, indicizzazione…) prima di ottenere una risposta.
Quando ha senso usare EDA ✅
EDA brilla quando:
- una singola azione genera fan-out (molti effetti collaterali);
- vuoi disaccoppiare domini e farli evolvere indipendentemente;
- hai carichi variabili e ti serve un buffer naturale;
- accetti (o desideri) eventual consistency.
Esempi tipici: notifiche, pipeline dati, antifrode, aggiornamento indici di ricerca, integrazioni tra domini.
Quando NON usarla (o almeno: non subito) 🛑
EDA è fantastica per fan-out e disaccoppiamento, ma non è magia: ti sposta complessità dal codice “sincrono” all’operatività e ai contratti. Se oggi non hai basi minime (log, metriche, ownership), rischi di pagare interessi composti.
- flussi che richiedono risposta immediata e consistenza stretta end-to-end;
- CRUD “semplice” senza integrazioni reali;
- team/organizzazione non pronti a gestire operatività e governance.
EDA aumenta potenza e flessibilità, ma aggiunge superficie operativa: se oggi non hai log e tracing decenti, EDA non ti “salva”… ti mette in palestra con i pesi legati alle caviglie.
Framework decisionale rapido 🧭
Usa queste domande come filtro iniziale:
- L’utente deve aspettare la fine di tutto? Se no → asincrono possibile.
- Ci sono più consumer potenziali oggi o domani? Se sì → eventi aiutano.
- L’azione produce side effects indipendenti? Se sì → fan-out naturale.
- Siamo pronti per DLQ, retry, idempotenza, osservabilità? Se no → rischio.
Trade-off reali (quelli che scopri in produzione) ⚖️
Finché stai in slide deck, EDA sembra solo vantaggi. In produzione scopri presto il conto: debug più difficile, consistenza eventuale da spiegare al business e overhead operativo. Non è un motivo per evitarla: è un motivo per adottarla in modo deliberato, con strumenti e processi prima del picco di traffico, non dopo.
Glossario minimo (per non litigare in riunione) 📚
Due minuti spesi qui spesso risparmiano due settimane di “ma per topic intendi queue o stream?”. Non è un dizionario: è giusto il minimo sindacale per parlare la stessa lingua.
- Topic/stream: canale logico di eventi. Non è solo un nome: definisce scope, retention e chi è responsabile, quindi influisce su costi e governance.
- Consumer group: più consumer che si dividono il lavoro (scalabilità orizzontale). Definisce come scali il processamento; scegliere male la chiave di partizionamento porta a hotspot o a perdita di ordering.
- DLQ: “parcheggio” per eventi problematici. È utile solo se esiste un processo per triage e reprocess; senza runbook diventa una discarica dimenticata.
- Correlation ID: filo rosso che collega eventi e operazioni. Ti salva ore di investigazione: se non lo propaghi, ritrovare la storia di un flusso asincrono diventa un rompicapo.
Prossimi passi 🚀
Se questo capitolo ti è sembrato “facile”, tranquillo: la parte interessante arriva con contratti e schema evolution, delivery semantics e governance.
- Per comunicazione e flussi: vedi la guida sui pattern.
- Per la scelta tra queue/stream/pub-sub: vedi la guida di messaggistica.
- Per evitare di rompere i contratti: vedi la guida su event design.