Schema Registry: contratti che sopravvivono nel tempo 🗄️
La guida su event design ti dice come pensare ai contratti. Questa ti dice con che strumenti li fai rispettare prima che un campo rinominato mandi fuori servizio tre consumer alle 2 di notte.
Il problema che risolve (e che senza registry rimane irrisolto) 🧠
Senza uno schema registry:
- ogni team gestisce versioni degli eventi con documenti Word, wiki o “lo sappiamo noi”;
- i consumer scoprono breaking change in produzione;
- non esiste un posto unico dove vedere tutte le versioni di uno schema;
- la compatibilità è a responsabilità individuale, che nella pratica vuol dire “a responsabilità di nessuno”.
Uno schema registry è un servizio centralizzato che:
- raccoglie gli schemi degli eventi (Avro, Protobuf, JSON Schema);
- valida i messaggi prima che arrivino sul broker;
- controlla la compatibilità tra versioni degli schema;
- espone API per producer e consumer.
Come funziona in pratica ⚙️
flowchart LR
P[Producer] -->|valida schema| SR[(Schema Registry)]
SR -->|schema ID| P
P -->|messaggio con schema ID| B[(Broker / Kafka)]
B --> C[Consumer]
C -->|recupera schema per ID| SR
C -->|deserializza payload| C
Il producer non include lo schema completo nel messaggio: include solo uno schema ID (pochi byte). Il consumer recupera lo schema dal registry tramite l’ID e deserializza il payload. Risultato: payload più compatti e fonte di verità centralizzata.
Modalità di compatibilità 🔄
La compatibilità si configura per subject (tipicamente per topic) o globalmente. Le modalità principali:
| Modalità | Descrizione | Uso tipico |
|---|---|---|
BACKWARD |
I nuovi consumer possono leggere i messaggi prodotti con la versione precedente | Più comune, evoluzione ordinaria |
FORWARD |
I vecchi consumer possono leggere i messaggi prodotti con la nuova versione | Quando non puoi aggiornare tutti i consumer subito |
FULL |
Compatibilità in entrambe le direzioni | External/public events, contratti stabili |
NONE |
Nessun controllo di compatibilità | Solo in sviluppo locale |
Regola pratica: inizia con BACKWARD, passa a FULL per gli external events. Non usare NONE in staging o produzione.
Formati di schema supportati 🧱
Apache Avro
Schema binario, compatto, con supporto nativo per campi nullable e evoluzione. È il formato più diffuso con Kafka.
|
|
Aggiungere il campo canale come nullable con default null è una modifica BACKWARD-compatible. Rimuovere importo sarebbe un breaking change.
Protocol Buffers (Protobuf)
Schema binario, cross-linguaggio, molto efficiente. Preferito in ambienti poliglotti o con requisiti di payload compatto. Richiede compilazione degli stub (.proto → codice nei linguaggi target).
JSON Schema
Leggibile, familiare, ma con supporto più limitato per l’evoluzione automatica rispetto ad Avro. Utile se il team non vuole il tooling di Avro/Protobuf o lavora prevalentemente con REST + JSON.
I registry più diffusi 🗂️
Confluent Schema Registry
Il riferimento de facto per Kafka. Distribuito sotto licenza Community (open source per uso self-hosted), con tier enterprise.
- integrazione nativa con producer/consumer Kafka via serializzatori (Avro, Protobuf, JSON Schema);
- API REST per gestire schemi, versioni e configurazioni di compatibilità;
- incluso in Confluent Platform e Confluent Cloud;
- supporta tutti e tre i formati.
Apicurio Registry
Registry open source (Apache License 2.0) sviluppato da Red Hat. Supporta Avro, Protobuf, JSON Schema e AsyncAPI, il che lo rende un buon candidato per chi vuole integrare catalogo e registry in un unico strumento.
- compatibile con l’API Confluent Schema Registry (drop-in replacement per chi migra);
- disponibile standalone o integrato in Red Hat OpenShift / AMQ Streams;
- supporta artifact lifecycle:
ENABLED,DEPRECATED,DISABLED.
AWS Glue Schema Registry
Registry gestito su AWS, integrato nativamente con MSK (Managed Kafka), Kinesis Data Streams e AWS Lambda.
- zero infrastruttura da gestire;
- integrazione via AWS SDK;
- supporta Avro e Protobuf;
- IAM per controllo accessi nativo.
Ideale se sei già su AWS e vuoi evitare un servizio aggiuntivo da mantenere.
Schema evolution in pratica: cosa puoi fare e cosa no 🧬
Con Avro + Confluent Registry in modalità BACKWARD:
| Operazione | Compatibile? |
|---|---|
| Aggiungere campo optional (nullable con default) | ✅ Sì |
| Aggiungere campo required (senza default) | ❌ No |
| Rimuovere campo con default | ✅ Sì (BACKWARD) |
| Rimuovere campo required | ❌ No |
| Rinominare un campo | ❌ No (equivale a remove + add) |
| Cambiare tipo di un campo | ❌ No (tranne promozioni sicure: int → long) |
Quando hai bisogno di un breaking change inevitabile: crea una versione v2 esplicita e mantieni un periodo di overlap in cui entrambe le versioni coesistono.
Integrazione con CI/CD 🔁
Non basta avere il registry in produzione: deve essere parte della pipeline di deploy.
flowchart LR
DEV[Sviluppo] -->|definisce schema| SR_DEV[Registry DEV]
CI[CI Pipeline] -->|check compatibilità — fail fast| SR_STG[Registry STG]
DEPLOY[Deploy] -->|promuove schema| SR_PROD[Registry PROD]
Pratiche consigliate:
- Schema-first: definisci lo schema prima di implementare producer e consumer — non dopo;
- Gate in CI: il check di compatibilità fallisce la pipeline, non è solo un warning;
- Promozione per ambiente: DEV → STG → PROD, non registrare direttamente in produzione.
Checklist adozione Schema Registry ✅
- Hai scelto il formato (Avro / Protobuf / JSON Schema) in modo coerente per tutti gli eventi?
- Hai configurato la modalità di compatibilità per ogni subject/topic?
- Il controllo di compatibilità è parte del processo di CI/CD?
- Il registry ha SLO definiti? (È una dependency critica per producer e consumer.)
- Hai un piano di migrazione per gli eventi legacy non ancora in registry?
- I team sanno come aggiornare uno schema, promuoverne una versione e gestire un breaking change?
Prossimi passi 🚀
- Per progettare lo schema degli eventi dal punto di vista del dominio: vedi la guida su event design.
- Per documentare e catalogare gli eventi con tool concreti: vedi la guida su tool ed ecosistema.
- Per testing degli schemi in CI: vedi la guida su testing.