Governance EDA: event catalog, ownership e anti “event spaghetti” 🧭
EDA scala benissimo tecnicamente.
Il problema è che spesso scala benissimo anche il caos.
Questa guida serve a evitare l’effetto “abbiamo 200 topic e nessuno sa perché”.
Perché serve governance (prima che sia tardi) 🧠
Il problema non è “la tecnologia”: è che senza regole condivise ogni team ottimizza localmente e il sistema globale diventa incomprensibile. Gli incidenti, a quel punto, non sono bug: sono conseguenze.
Senza governance:
- eventi duplicati con nomi diversi;
- consumer che dipendono da dettagli interni;
- breaking change “silenziosi”;
- topic creati come funghi;
- incidenti difficili da diagnosticare.
Con governance minimale:
- contratti espliciti;
- ownership chiara;
- discoverability;
- evoluzione controllata.
Event catalog: mappa del tuo ecosistema 🗺️
flowchart LR
PR[Proposta evento] --> REV["Review<br/>(naming/schema/privacy)"]
REV --> PUB["Pubblicazione<br/>+ doc + schema"]
PUB --> CAT["Event catalog"]
CAT --> DISC["Discoverability<br/>chi pubblica/consuma"]
PUB --> DEP["Deprecazione"]
DEP --> RET["Retire"]
Un event catalog dovrebbe rispondere a:
- quali eventi esistono?
- chi li pubblica?
- chi li consuma?
- qual è lo schema e la semantica?
- qual è lo stato del lifecycle? (attivo, deprecato, legacy)
Non deve essere un tomo infinito: deve essere trovabile e aggiornato.
Ownership: chi risponde quando qualcosa va male 👤
Ownership non è “il nome di un team scritto in un wiki dimenticato”: è la garanzia che esiste qualcuno in grado di rispondere quando qualcosa non funziona — e che sa perché quell’evento esiste.
Ogni evento o topic dovrebbe avere:
- un team owner identificato (con persona di riferimento reale, non solo un alias generico);
- un canale di contatto raggiungibile (Slack, email, on-call rotation);
- SLO minimi dichiarati: latenza attesa, retention window, garanzie di affidabilità.
Senza owner non sei in una situazione di “ownership condivisa”: sei in una situazione di assenza di ownership, che è molto diversa. Gli eventi orfani si accumulano, nessuno osa toccarli, e a un certo punto qualcuno si chiede se è sicuro deprecarli. Non lo sa. Nessuno lo sa. Questo è il vero “event spaghetti”.
Una buona ownership registry dovrebbe essere parte del catalogo stesso: non un foglio Google separato che si sincronizza (male) con la realtà, ma una fonte di verità unica aggiornata contestualmente al ciclo di vita dell’evento.
“Se tutti sono responsabili, nessuno è responsabile.” — vale per i microservizi, per le API, e ovviamente per gli eventi.
Standard: naming, metadata, versioning 📏
Senza standard condivisi ogni team produce eventi con convenzioni proprie. Il risultato: OrderPlaced, order_placed, order-place-event, PlaceOrderCommand — tutti che fanno cose simili, spesso in sistemi diversi, mai interoperabili senza trasformazioni ad hoc.
Naming
La regola più diffusa (e sensata) per gli eventi è il past tense + sostantivo di dominio:
OrderPlaced,PaymentFailed,UserRegistered;- evita verbi imperativi (quelli sono comandi, non eventi);
- prefissa con il bounded context se usi un event bus condiviso:
payments.PaymentFailed,orders.OrderShipped.
Per i topic/stream, una convenzione comune è {dominio}.{entità}.{versione} oppure {dominio}-{entità}-events, purché non cambi a metà progetto.
Metadata obbligatori
Ogni evento dovrebbe portare con sé un minimo di contesto trasversale:
|
|
event_id e occurred_at garantiscono tracciabilità e ordinamento; correlation_id permette di seguire una richiesta attraverso più servizi; schema_version è vitale per la compatibilità.
Schema evolution e compatibilità
Tre modalità, in ordine crescente di rigore:
- Backward compatible: aggiungi campi opzionali, non rimuovere e non rinominare quelli esistenti;
- Forward compatible: i consumer ignorano i campi che non conoscono;
- Full compatible: entrambe le direzioni simultaneamente.
In pratica: usa uno schema registry (Confluent, AWS Glue, Apicurio) per centralizzare gli schema, imporre compatibilità e versioning esplicito. Il registro diventa la fonte di verità contrattuale, non un dettaglio infrastrutturale.
Standard non vuol dire burocrazia: vuol dire evitare che ogni team reinventi l’alfabeto — e poi non riesca più a comunicare con gli altri.
Organizzazione, dominio e confini: Conway non perdona 🏛️
C’è una legge che nessuno può eludere: la Conway’s Law. “Le organizzazioni generano sistemi che rispecchiano la loro struttura di comunicazione.” Applicata a EDA: se i team comunicano male, gli eventi saranno incoerenti; se ownership e confini sono chiari, anche i contratti tendono a esserlo.
Non è una previsione: è un’osservazione empirica verificata in ogni azienda abbastanza grande da avere “quella parte del sistema che nessuno vuole toccare”.
Bounded context come unità di coerenza
EDA e DDD (Domain-Driven Design) si combinano naturalmente: i bounded context definiscono i confini entro cui un modello di dominio è coerente e comprensibile. Ogni contesto dovrebbe:
- pubblicare eventi che riflettono il proprio linguaggio ubiquo (ubiquitous language);
- non esporre dettagli interni (il modello del database, le entità di persistenza);
- evolvere indipendentemente dagli altri contesti.
Un OrderPlaced nel contesto Ordini potrebbe avere una semantica diversa da ciò che il contesto Spedizioni si aspetta. Questo è normale: l’importante è non far “trapelare” i dettagli interni attraverso i confini.
Anti-corruption layer
Quando un servizio deve consumare eventi di un dominio esterno, l’anti-corruption layer (ACL) traduce gli eventi in arrivo nel proprio modello interno. I vantaggi sono concreti:
- il consumer è isolato dai cambiamenti del producer;
- il linguaggio interno del team non è “contaminato” da modelli altrui;
- i breaking change del producer diventano un problema dell’ACL, non dell’intero sistema consumer.
Governance efficace significa anche ridurre carico cognitivo: meno ambiguità, naming prevedibile, catalogo ricercabile, confini espliciti. Tutto ciò che non deve essere capito non dovrebbe essere esposto.
Processi leggeri ma reali 🔁
“Processo” non deve far paura: bastano pochi passaggi espliciti per evitare che il catalogo eventi diventi un selvaggio west. Ecco un esempio sostenibile, pensato per team di medie dimensioni.
1. Proposta
Chi vuole pubblicare un nuovo evento apre una proposta — issue, ADR, o PR su un repo di governance — che include:
- nome dell’evento e bounded context di appartenenza;
- motivazione e use case (perché esiste, cosa rappresenta);
- consumer target (chi si prevede lo consumi);
- bozza di schema.
2. Review
Non è un comitato burocratico, ma una verifica distribuita su:
- rispetto degli standard di naming e metadata;
- compatibilità con eventi esistenti (duplicati? conflitti semantici?);
- implicazioni di privacy e compliance (GDPR, dati sensibili nel payload?);
- approvazione da almeno un altro team che conosce l’area di dominio.
3. Pubblicazione
Merge nel catalogo con:
- schema definitivo registrato nello schema registry;
- documentazione minima: semantica, quando viene emesso, cosa significa;
- owner dichiarato e contatto;
- stato del lifecycle impostato a
active.
4. Deprecazione e retire
Cambia lo stato nel catalogo, notifica i consumer noti, definisci una finestra di supporto (es. 3 mesi), poi ritira. Automatizza i reminder dove possibile — nessuno ricorda le scadenze spontaneamente.
Il segreto è che il processo esiste per iscritto e viene usato davvero: anche con qualche compromesso è infinitamente meglio della situazione spontanea.
Checklist governance ✅
Se vuoi una cartina tornasole per capire se siete già in zona “event spaghetti”, questa è un buon inizio. Non serve essere perfetti: serve essere espliciti.
- Catalogo: deve essere ricercabile e ogni entry deve includere almeno schema, owner e stato del lifecycle.
- Owner: per ogni evento/topic indica un contatto e un canale (es. Slack/Email) e definisci SLO minimi.
- Standard metadata/naming: pubblica uno standard con esempi e casi d’uso, includendo template per proporre nuovi eventi.
- Policy breaking change: definisci finestra di supporto e processo di deprecazione (automatizzato o manuale, ma reale).
- DLQ e reprocessing: documenta runbook, ownership e come testare il reprocess in staging.
Prossimi passi 🚀
Governance senza operatività è teoria; operatività senza governance è caos efficiente. Ti servono entrambe.
- Per operatività: vedi la guida su delivery semantics e DLQ.
- Per contratti: vedi la guida su event design.