Registre des schémas et évolution des données
Pourquoi avez-vous besoin d'un registre des schémas
Le registre des schémas est une source centralisée de vérité pour les contrats de données (API, événements, flux, messages, stockage) qui fournit :- Évolution prévisible : règles de compatibilité et vérification automatique des « cassures ».
- Répétabilité et transparence : historique des versions, qui/quand/pourquoi a changé.
- Standardisation : noms uniques, formats d'erreur, champs de trace, étiquettes PII.
- Intégration avec CI/CD : verrouillage des modifications de rupture avant la production.
Le registre lie Protocol-first et l'interopérabilité contractuelle, rendant les changements rapides et sécurisés.
Formats et domaines d'application
JSON Schema : REST/HTTP charges utiles, documents, configurations.
Avro : pneus événements (Kafka/Pulsar), compact/evolution via ID de champs.
Protobuf : gRPC/RPC, efficace binaire, étiquettes strictes.
GraphQL SDL : schéma des types et directives, évolution via '@ deprecated'.
SQL DDL en tant qu'artefact : nous fixons les vues négociées (par exemple, les vitrines externes) - avec prudence.
Modes de compatibilité
BACKWARD : les nouveaux schémas lisent les anciennes données/messages. Convient au producteur qui étend payload additivement.
FORWARD : les anciens consommateurs lisent correctement les nouvelles données (nécessite un lecteur tolérant).
FULL : combine les deux (plus strict, plus pratique pour les marchés publics).
NONE : aucun contrôle - uniquement pour les bacs à sable.
- Événements : plus souvent BACKWARD (le producteur étend payload en option).
- API publiques : FULL ou BACKWARD + lecteur tolérant strict sur les clients.
- Prototypes internes : Temporairement NONE, mais pas sur trunk.
Sécurité (additif) vs. modifications dangereuses
Additif (OK) :- Ajoute un champ/type facultatif.
- Extension enum avec de nouvelles valeurs (avec tolérant reader).
- Ajoute une autre projection/événement ('.enriched').
- Assouplissement des contraintes ('minLength', 'maximum' ↑ mais pas ↓).
- Supprimer/renommer les champs ou modifier leur type/obligation.
- Modification de la sémantique des statuts/codecs/ordre dans les flux.
- Réutilisation des étiquettes protobuf.
- Change la clé de lot dans les événements.
Organisation du Registre
Neuming et adressage
Groupes/espaces : 'payments', 'kyc', 'audit'.
Noms : 'payment. authorized. v1` (events), `payments. v1. CaptureRequest` (gRPC), `orders. v1. Order` (JSON Schema).
Majeur dans le nom, mineur - dans les métadonnées/version du schéma.
Métadonnées
'owner' (commande), 'domain', 'slas' (SLO/SLA), 'security. tier` (PII/PCI), `retention`, `compatibility_mode`, `sunset`, `changelog`.
Gestion du cycle de vie
Draft → Review → Approved → Released → Deprecated → Sunset.
Validateurs/linters automatiques, conception-révision manuelle (API Guild), release notes.
Intégration dans CI/CD
1. Pré-commit : linters locaux (Spectral/Buf/Avro tools).
2. PR-pipline : schema-diff → vérification de la compatibilité en mode ; on bloque le breaking.
3. Artifact publish : push schéma convenu dans le registre + génération SDK/modèles.
4. Runtime-guard (facultatif) : La passerelle/productrice valide payload contre le schéma actuel.
- `openapi-diff --fail-on-breaking`
- `buf breaking --against
` - `avro-compat --mode BACKWARD`
- génération de samples d'or et exécution de tests CDC.
Évolution des schémas : pratiques
Additive-first: новые поля — `optional/nullable` (JSON), `optional` (proto3), default в Avro.
Le modèle de la pyramide inverse : le noyau est stable, l'enrichissement est proche et facultatif.
Dual-emit/dual-write pour major : nous publions « v1 » et « v2 » en parallèle.
Sunset-plan : dates, utilisation, avertissements, adaptateurs.
Lecteur Tolérant : les clients ignorent les champs inconnus et gèrent correctement les nouveaux enum.
Exemples de schémas et de contrôles
JSON Schema (fragment, champ additif)
json
{
"$id": "orders. v1. Order",
"type": "object",
"required": ["id", "status"],
"properties": {
"id": { "type": "string", "format": "uuid" },
"status": { "type": "string", "enum": ["created", "paid", "shipped"] },
"risk_score": { "type": "number", "minimum": 0, "maximum": 1 }
},
"additionalProperties": true
}
Avro (par défaut pour la compatibilité)
json
{
"type": "record",
"name": "PaymentAuthorized",
"namespace": "payment. v1",
"fields": [
{ "name": "payment_id", "type": "string" },
{ "name": "amount", "type": "long" },
{ "name": "currency", "type": "string" },
{ "name": "risk_score", "type": ["null", "double"], "default": null }
]
}
Protobuf (n'utilisez pas trop de balises)
proto syntax = "proto3";
package payments. v1;
message CaptureRequest {
string payment_id = 1;
int64 amount = 2;
string currency = 3;
optional double risk_score = 4; // additive
}
//tag = 4 is reserved for risk_score and cannot be changed/deleted without v2
Registre des événements et lot
Nommage des événements : 'domain. action. v{major}` (`payment. captured. v1`).
La clé de lot fait partie du contrat ('payment _ id', 'user _ id').
Core vs Enriched : '.v1' (noyau) et '.enriched. v1 '(détails).
Compatibilité dans le registre : modes au niveau du sujet/type ; CI refuse les modifications incompatibles.
Gestion des migrations
Expand → Migrate → Contract (REST/gRPC):1. ajouter des champs/tables ; 2) commencer à écrire/lire de nouveaux champs ; 3) supprimer l'ancien après sunset.
- Dual-emit (Events) : parallèle à 'v1 '/' v2', migration consumers/projections, puis retrait de 'v1'.
- Replay : recalculer les projections de la loge vers le nouveau schéma (uniquement avec la compatibilité et les migreurs).
- Adaptateurs : gateway/proxy traduisant 'v1↔v2' pour les clients complexes.
Sécurité et conformité
PII/PCI de l'étiquette dans le schéma : 'x-pii : true', 'x-sensibility : high'.
Politiques d'accès : qui peut publier/modifier des schémas (RBAC), signer des versions.
Cryptographie : signature des versions des schémas, journaux d'audit immuables (WORM).
Droit à l'oubli : spécifiez les champs nécessitant un chiffrement/un chiffrement ; guidance dans le registre.
Observation et audit
Dashboards : nombre de changements, types (mineur/majeur), proportion de RP rejetés, utilisation des versions.
Audit-trail : qui a modifié le schéma, liens vers PR/ADR, version associée.
Runtime-métriques : pourcentage de messages qui n'ont pas été validés ; incidents de compatibilité.
Outils (pile approximative)
OpenAPI/JSON Schema: Spectral, OpenAPI Diff, Schemathesis.
Protobuf/gRPC: Buf, buf-breaking, protoc linters.
Avro/Events: Confluent/Redpanda Schema Registry, Avro-tools, Karapace.
GraphQL: GraphQL Inspector, GraphQL Codegen.
Registres/catalogues : Artifact Registry, Git-based registry, Backstage Catalogue, custom UI.
Documentation : Redocly/Stoplight, Swagger-UI, GraphiQL.
Anti-modèles
Swagger-wash : le schéma ne reflète pas la réalité du service (ou vice versa).
Vérification de compatibilité désactivée : « urgent » → la faille se brise.
Réutilisation des étiquettes protobuf : corruption silencieuse des données.
Un seul mode de compatibilité « pour tout » : différents domaines nécessitent différents modes.
Les CDC bruts comme schémas publics : fuite du modèle OBD vers l'extérieur, impossibilité d'évolution.
Chèque d'implémentation
- Le format des artefacts et le mode de compatibilité par domaine ont été définis.
- Les linters et schema-diff sont configurés dans CI, PR est bloqué lors du breaking.
- Inclus dans le lecteur tolérant chez les clients ; 'additionalProperties = true' (le cas échéant).
- Les changements majeurs passent par RFC/ADR, il y a un plan sunset et dual-emit/dual-write.
- Les schémas sont marqués PII/PCI et les niveaux d'accès ; un audit est inclus.
- Dashboards sur l'utilisation des versions et les défauts de compatibilité.
- La génération de SDK/modèles à partir du registre fait partie de la pipline.
- Documentation et samples d'or mis à jour automatiquement.
FAQ
Est-il possible de stocker des schémas dans Git sans registre ?
Oui, mais le registre ajoute l'API de compatibilité, la recherche, les métadonnées, la politique centralisée et la validation « on-the-fly ». La meilleure option est Git comme storage + UI/stratégies en plus.
Comment choisir le mode de compatibilité ?
Regardez la direction du changement : si le producteur étend payload - BACKWARD. Pour l'API/SDK public - FULL. Pour les prototypes rapides - temporairement NONE (pas sur trunk).
Que faire en cas de besoin ?
Nous préparons v2 : dual-emit/dual-run, sunset-days, adaptateurs, télémétrie d'utilisation, hydes de migration.
Dois-je valider payload dans rantime ?
Pour les domaines critiques - oui : cela empêche les messages « poubelle » et accélère le diagnostic.
Résultat
Le registre des schémas transforme l'évolution des données de l'improvisation risquée en un processus contrôlé : règles d'interopérabilité uniques, vérifications automatiques, versions compréhensibles et historique transparent. Ajoutez à cela la discipline additive-first, tolérant reader, dual-emit et sunset - et vos contrats évolueront rapidement, sans cassures ni incidents nocturnes.