Concevoir pour la vélocité : plaidoyer pour une ingestion d'événements sans schéma

SchemaBridge Team · 2025-12-08 · Event Ingestion, JSON, DX

Vitesse contre typage strict dans les systèmes orientés événements. Pourquoi nous avons choisi le JSON brut plutôt que des définitions de types strictes.

Le paradoxe du schéma : ami ou ennemi ?

Dans le logiciel d'entreprise traditionnel, les schémas stricts (SQL, Protobuf, WSDL) sont le socle de la fiabilité. Le contrat est simple : je définis la forme des données, vous vous y conformez, et le compilateur garantit que nous ne planterons pas. Cette approche nous a bien servis pendant des décennies dans des environnements contrôlés où nous possédons les deux extrémités du tuyau. Elle offre une sûreté à la compilation, une sérialisation binaire efficace, et une « source de vérité » claire pour les développeurs.

Mais dans un environnement d'intégration moderne à haute vélocité — où les fournisseurs SaaS modifient leurs payloads chaque semaine, où les ERP legacy émettent des CSV « flexibles », et où les microservices internes naissent et sont retirés chaque mois — les schémas rigides deviennent une camisole de force. Ils offrent la sûreté au prix de l'inertie. Quand le monde qui vous entoure est fluide, un contrat rigide n'est pas une fondation ; c'est un point de défaillance. Le paradoxe du schéma est le suivant : plus vous essayez de protéger votre système avec des types stricts, plus vous le rendez fragile lorsque le monde extérieur évolue.

L'évolution historique : de COBOL à JSON

Pour comprendre la demande de systèmes sans schéma, nous devons examiner l'évolution de l'échange de données. Aux débuts de l'informatique sur mainframe, les données étaient stockées dans des enregistrements de longueur fixe (les COPYBOOK COBOL). Si vous vouliez ajouter un champ, vous deviez recompiler chaque programme qui lisait cet enregistrement. C'était le schéma rigide ultime. C'était l'ère de « l'état d'esprit machine unique », où le coût du stockage de données était si élevé que chaque octet devait être comptabilisé à une position fixe. Il n'y avait aucune place pour la hiérarchie, aucune place pour l'optionnalité, et certainement aucune place pour l'évolution. Chaque caractère d'un enregistrement était une ressource précieuse, et le moindre changement était un événement sismique nécessitant des semaines de planification et de tests.

Dans les années 1980 et 1990, nous nous sommes tournés vers les bases de données relationnelles et SQL. Ce fut une avancée massive, car cela introduisait le concept de relations structurées. Mais cela a aussi introduit la migration de base de données. Ajouter une colonne signifiait de l'indisponibilité, des tables verrouillées, et une coordination minutieuse entre DBA et développeurs. Le schéma restait un mur que les développeurs devaient escalader chaque fois qu'ils voulaient innover. Même avec l'essor d'ORM comme Hibernate, la rigidité sous-jacente de la structure de table demeurait l'arbitre final de ce qui était possible.

Puis sont arrivés XML et SOAP à la fin des années 1990. Cela a introduit le concept de « balises », permettant une certaine flexibilité. Vous pouviez ajouter une balise XML sans nécessairement casser le parseur. Cependant, l'industrie a rapidement ajouté XSD (XML Schema Definition) et les WSDL, qui ont ramené la rigidité. Nous avons passé des années à nous battre avec des namespaces et des enterprise service bus complexes qui rejetaient un message si un seul caractère était déplacé. C'était l'« âge sombre de XML », où la surcharge du schéma consommait plus de bande passante que les données elles-mêmes.

Aujourd'hui, nous avons JSON et REST. JSON est naturellement flexible. Ce n'est qu'une simple map de clés et de valeurs. Pourtant, nos instincts d'ingénieurs nous poussent encore à envelopper cette flexibilité dans des types stricts (interfaces TypeScript, DTO Java, schémas Avro). Nous essayons d'imposer la rigidité des mainframes des années 1970 aux événements cloud des années 2020. Pourquoi ? Parce que nous craignons l'inconnu. Nous craignons qu'un champ manquant ne fasse planter notre service. Mais comme nous allons le voir, cette peur est traitée avec les mauvais outils.

L'analyse financière : la « taxe cachée » de la maintenance des intégrations

Quantifions le coût de la rigidité des schémas. Dans une organisation d'ingénierie de taille moyenne à grande typique, la maintenance des intégrations est une « crise silencieuse ». Elle n'apparaît pas comme une ligne dans un bilan comptable, mais elle constitue un frein massif à la productivité.

Les mathématiques de la maintenance

Supposons qu'une organisation ait 100 intégrations SaaS externes.

En termes de salaire, cela représente plus de $150,000 USD dépensés chaque année juste pour « réparer la plomberie ». Mais le coût réel est le coût d'opportunité. Pendant que vos ingénieurs seniors mettent à jour des DTO pour la mise à jour Stripe v2025, ils ne construisent pas la nouvelle fonctionnalité de détection automatisée de fraude qui pourrait faire économiser des millions à l'entreprise. Sur une période de 5 ans, cette taxe se traduit par une perte cumulée de vélocité qui peut mettre une entreprise des années en retard sur ses concurrents plus agiles.

La philosophie de la fluidité des données : le Schema-on-Read

Chez SchemaBridge, nous plaidons pour un changement fondamental de mentalité : le Schema-on-Read.

Au lieu de valider les données au moment de leur entrée (Schema-on-Write), nous ingérons d'abord la vérité brute et hiérarchique de l'événement. Nous préservons chaque octet du payload JSON dans notre magasin durable. Nous n'appliquons un schéma — ou plus précisément une transformation — qu'au moment où les données sont nécessaires à un processus métier spécifique.

Pourquoi la fluidité des données gagne

1. Ingestion sans intervention : vous pouvez commencer à recevoir des événements d'un nouveau fournisseur en quelques secondes. Pointez le webhook vers une Gateway SchemaBridge, et les données commencent à circuler immédiatement vers le magasin durable. Vous pourrez comprendre ce que signifient les données plus tard.

2. Une assurance contre l'inconnu : si un fournisseur ajoute aujourd'hui un champ dont vous n'avez pas besoin, il est quand même capturé dans le JSON brut. Si vous réalisez dans six mois que vous avez besoin de ce champ, les données historiques sont déjà là. Vous n'avez pas à retourner demander au fournisseur d'anciennes données.

3. Une évolution découplée : votre couche d'ingestion et votre couche de transformation peuvent évoluer à des vitesses différentes. Vous pouvez mettre à jour votre logique métier 10 fois par jour sans jamais toucher à vos gateways d'ingestion.

L'argument mathématique en faveur du Late-Binding

En informatique, le Late-Binding est la pratique consistant à retarder la résolution d'une identité ou d'un type jusqu'au moment de l'exécution. C'est ce qui rend les langages dynamiques comme Ruby ou Python si puissants pour certaines tâches.

Le Schema-on-Read est du late-binding appliqué à votre infrastructure de données. En retardant le mapping, vous passez d'un graphe rigide (où chaque changement nécessite une reconstruction complète) à un chemin flexible (où le chemin peut s'adapter au terrain à mesure qu'il avance).

Mathématiquement, le nombre de mappings potentiels entre $N$ producteurs et $M$ consommateurs est $N \times M$. Si chaque producteur et chaque consommateur doivent s'accorder sur un schéma strict, vous avez un problème de coordination massif. Si vous utilisez un pont sans schéma avec du late-binding, vous réduisez le problème à $N + M$ mappings, où chaque mapping est local et indépendant. C'est ainsi que vous atteignez une véritable échelle d'ingénierie horizontale.

JSONata : la masterclass du traitement événementiel fonctionnel

Pour rendre le Schema-on-Read praticable, il vous faut un langage conçu pour la découverte. Nous avons choisi JSONata. JSONata n'est pas seulement un langage de requête ; c'est un moteur de transformation fonctionnel qui opère directement sur la hiérarchie JSON brute.

L'anatomie d'une expression JSONata

Considérez un payload provenant d'un ERP legacy qui renvoie une liste de commandes. Chaque commande a une structure complexe et imbriquée. Vous voulez extraire tous les numéros de pièce pour les commandes dont le montant dépasse $500 et qui sont actuellement dans l'état 'SHIPPING'.

Le code traditionnel (JavaScript) :

const parts = payload.orders
  .filter(o => o.total > 500 && o.status === 'SHIPPING')
  .flatMap(o => o.items)
  .map(i => i.partNumber);

Ce code est fragile. Si orders est null, ou si items est manquant pour une commande, il plante.

La maîtrise JSONata :

orders[total > 500][status = 'SHIPPING'].items.partNumber

Cette expression est null-safe. Si orders est manquant, le résultat est simplement un tableau vide. Elle ne lève jamais d'exception. Elle « découvre » les données plutôt que de les « présupposer ».

Pattern avancé : la sélection profonde de descendants

L'une des fonctionnalités les plus puissantes de JSONata est l'opérateur **. Il vous permet de trouver n'importe quelle clé, peu importe où elle se trouve dans la hiérarchie.

$**.tracking_number

Si vos fournisseurs en aval utilisent tous une imbrication différente pour les numéros de suivi, cette seule expression les trouvera tous, à travers chaque version différente de payload. C'est la définition de la résilience structurelle. Elle transforme une chasse fragile à une clé spécifique en une recherche flexible de la vérité.

Pattern avancé : la restructuration des données à la volée

JSONata vous permet de reconstruire l'intégralité de l'objet JSON en une seule passe.

orders.{ "order_id": ID, "summary": $join(items.name, ', ') }

Dans du code traditionnel, cela nécessite du mapping d'objets, de la concaténation de chaînes, et de l'itération de tableaux. En JSONata, c'est une projection déclarative de l'état désiré. C'est particulièrement puissant lorsque vous devez envoyer un résumé simplifié d'un événement complexe vers une notification Slack ou une application mobile.

Opérationnaliser des données sans table : sécurité et validation

Les critiques demandent souvent : « Si nous n'utilisons pas de schémas, comment empêchons-nous que n'importe quoi n'entre dans notre système ? »

La réponse est que sans schéma != non validé. Nous déplaçons simplement la validation au niveau du sommet.

Étude de cas : le maillage d'ingestion de données à 50 régions

Nous avons récemment travaillé avec une entreprise IoT mondiale qui ingérait de la télémétrie provenant de 50 régions différentes, chacune utilisant une version légèrement différente de son firmware de capteurs. Chaque région avait son propre « dialecte » de JSON.

Le défi

Ils ont essayé d'utiliser un système d'ingestion traditionnel basé sur SQL, avec un schéma de table strict. Chaque fois qu'une mise à jour de firmware était déployée dans un seul pays, tout le pipeline d'ingestion de ce pays cassait, car le nouveau firmware ajoutait un champ battery_health_v2 pour lequel la base de données n'avait pas de colonne. L'équipe data était constamment en mode « pompier », exécutant des commandes ALTER TABLE sur 50 bases de données de production. Ils perdaient des millions d'événements pendant ces fenêtres de maintenance.

La solution SchemaBridge

Ils sont passés à une stratégie sans schéma.

1. Capture universelle : les 50 régions ont pointé leurs données vers un unique cluster Gateway SchemaBridge. Les Gateways ne se souciaient pas du schéma ; elles se contentaient de persister les événements bruts.

2. Mapping à la lecture : ils ont créé 50 « sommets de normalisation » différents (un par version de firmware). Le workflow identifiait la version du firmware à partir de l'en-tête et routait le JSON brut vers le sommet correct.

3. Mises à jour sans code : lorsqu'une nouvelle version de firmware était lancée, ils n'avaient pas besoin de mettre à jour la base de données. Ils dupliquaient simplement le sommet existant, mettaient à jour le mapping JSONata pour inclure les nouveaux champs, et déployaient.

Le résultat

Conclusion : la vélocité est un choix de conception

Les schémas stricts sont un choix. C'est le choix de prioriser la sûreté statique par rapport à la vélocité dynamique. Dans un système fermé, c'est un choix valide. Dans un écosystème connecté et distribué, c'est un choix qui mène à l'échec.

Concevez vos systèmes pour le monde tel qu'il est — imprévisible, évolutif et hiérarchique. Concevez pour la vélocité. Concevez avec SchemaBridge. En embrassant la fluidité des données, vous débloquez la capacité de construire, de passer à l'échelle et d'innover à une vitesse dont vos concurrents — coincés dans leurs DTO rigides et leurs migrations de base de données — ne peuvent que rêver.

Dans la Partie 3, nous passons de l'ingestion à l'exécution, en explorant le sommet « Spawner » et comment maîtriser les fan-outs distribués à l'échelle de plus de 10 000 éléments. Rejoignez-nous pour voir comment gérer des millions d'événements sans faire planter vos serveurs ni perdre une seule transaction. Reconquérir la puissance de la boucle dans un contexte distribué.

Explorer