Une banque doit approuver ou refuser une transaction en 200 millisecondes. Une plateforme logistique doit rerouter 10 000 expéditions quand un port ferme. Un système manufacturier doit ajuster les paramètres de production avant qu'un défaut ne se propage le long de la ligne.

Ce ne sont pas des jobs batch. Ce sont des décisions en temps réel qui doivent être rapides, correctes et auditables. Et elles doivent fonctionner à l'échelle — pas des dizaines de décisions par minute, mais des milliers par seconde.

Nous construisons ces systèmes. Voici comment ils fonctionnent.

Pourquoi le Temps Réel Est Difficile

Prendre une seule décision rapide est facile. Prendre des milliers de décisions rapides par seconde, chacune correcte et traçable, avec une dégradation progressive sous charge — c'est un problème complètement différent.

Les défis s'accumulent :

Consistance sous concurrence. Quand deux décisions ont besoin des mêmes données et que ces données changent, il faut un modèle de consistance qui soit à la fois correct et rapide. La consistance forte tue la latence. La consistance éventuelle introduit des erreurs. Il faut être précis sur quelles données doivent être consistantes et lesquelles peuvent tolérer un certain retard.

Budget de latence. Dans un budget de bout en bout de 200ms, chaque composant reçoit une tranche. Réseau : 20ms. Récupération des données : 40ms. Inférence du modèle : 60ms. Règles métier : 30ms. Sérialisation de la réponse : 10ms. Il reste 40ms pour tout ce que vous avez oublié. Si un composant dépasse son budget, la décision manque la deadline.

Isolation des défaillances. Quand un service en aval échoue, il ne peut pas cascader dans le pipeline décisionnel. Un modèle de détection de fraude lent ne peut pas bloquer un paiement. Un service d'enrichissement défaillant ne peut pas empêcher une décision de routage. Chaque composant nécessite une gestion des défaillances indépendante.

Auditabilité à volume. Les régulateurs se moquent que vous preniez 50 000 décisions par seconde. Ils s'intéressent à une décision spécifique prise à 14:23:07 le 15 mars. Votre système doit produire une trace décisionnelle complète pour n'importe quelle décision individuelle sans impacter le débit.

L'Architecture

Nos systèmes décisionnels en temps réel suivent un pattern consistant, affiné à travers de multiples déploiements :

Pipeline Décisionnelle

Flux Événements → Enrichissement → Moteur Décisionnel → Dispatcher Actions → Log Audit
                     ↓                ↓                                       ↓
              Feature Store      Cache Modèle                          Trace Store

Chaque décision traverse cinq étapes :

  1. Ingestion des événements — Les événements arrivent via une file de messages. Chaque événement est immuable et horodaté. L'ordre est préservé au sein des partition keys.

  2. Enrichissement — L'événement brut est enrichi avec des données contextuelles du feature store. Historique client, attributs produit, scores de risque. Ces données sont pré-calculées et en cache — l'enrichissement est un lookup, pas un calcul.

  3. Moteur décisionnel — L'événement enrichi atteint le moteur décisionnel, qui applique une combinaison de règles déterministes et d'inférence du modèle. Les règles gèrent les cas courants. Les modèles gèrent les cas complexes. La répartition est configurable par type de décision.

  4. Dispatch des actions — La décision déclenche des actions en aval. Approuver la transaction. Rerouter l'expédition. Ajuster le paramètre. Les actions sont dispatchées de manière asynchrone — la décision est enregistrée avant que l'action ne se termine.

  5. Logging audit — Chaque décision produit une trace : entrées, données d'enrichissement, règles évaluées, scores du modèle, décision finale et niveau de confiance. Les traces sont écrites dans un store append-only pour la conformité et le débogage.

Le Feature Store

Le feature store est le composant le plus sous-estimé. C'est ce qui rend l'enrichissement suffisamment rapide pour respecter le budget de latence.

Les features sont pré-calculées sur deux échelles de temps :

  • Features batch — Mises à jour toutes les heures ou tous les jours. Valeur lifetime du client, patterns historiques, statistiques agrégées. Calculées par des pipelines batch et matérialisées dans le store.
  • Features streaming — Mises à jour en temps réel. Vitesse des transactions, comportement récent, données de la session en cours. Calculées par un stream processor et écrites dans le store avec une latence sous la seconde.

Au moment de la décision, l'étape d'enrichissement lit depuis le store. Aucun calcul. Juste un lookup clé-valeur. C'est ainsi que nous maintenons l'enrichissement sous les 40ms même quand le jeu de features inclut des centaines d'attributs.

Model Serving

L'inférence du modèle est le composant le plus variable dans la pipeline. Un modèle qui met en moyenne 30ms peut avoir des pics à 200ms sous charge. Nous gérons cela avec trois stratégies :

Distillation du modèle. Les modèles en production sont des versions distillées de nos modèles d'entraînement. Plus petits, plus rapides, optimisés pour l'inférence. La perte de précision est typiquement inférieure à 0,5% — un compromis que nous acceptons à chaque fois pour une amélioration de latence de 3x.

Timeout avec fallback. Si l'inférence du modèle dépasse son budget de latence, la décision bascule en mode règles uniquement. La décision est toujours prise. Elle est légèrement moins optimale, mais elle est ponctuelle. Nous suivons les taux de fallback comme métrique clé — un taux de fallback en hausse signifie que le modèle nécessite une optimisation.

Scaling horizontal avec routage. Les replicas du modèle sont équilibrées en charge avec un routage sensible à la latence. Les requêtes vont vers la replica avec la latence courante la plus basse, pas en round-robin. Cela atténue la variance de performance des replicas individuelles.

Modèle de Consistance

La décision architecturale la plus difficile est le modèle de consistance. Voici notre approche :

Les entrées décisionnelles sont eventually consistent. Les données du feature store peuvent avoir quelques millisecondes de retard. Pour la plupart des décisions, c'est acceptable. Le score de risque d'un client calculé il y a 500ms est suffisamment proche.

Les sorties décisionnelles sont strongly consistent. Une fois qu'une décision est prise, elle est immédiatement visible pour tous les systèmes en aval. Aucun délai, aucun conflit, aucun "le système l'a approuvée mais le tableau de bord affiche en attente."

Les traces décisionnelles sont immuables. Écrites une fois, jamais modifiées. Cela simplifie énormément l'historique d'audit. Pas besoin de suivre les modifications des enregistrements décisionnels car les enregistrements décisionnels ne changent pas.

Ce modèle de consistance mixte nous donne les performances des systèmes eventually consistent là où ça compte (données d'entrée) et la correction des systèmes strongly consistent là où ça compte (sorties et audit).

Patterns de Scaling

Les systèmes décisionnels en temps réel doivent gérer les pics de charge sans dégradation. Notre approche du scaling :

Partitionner par type de décision. Différents types de décisions ont des exigences de latence différentes et des profils de ressources différents. L'approbation de transactions a un budget de 200ms et nécessite des GPU pour l'inférence du modèle. Le routage d'expéditions a un budget de 2 secondes et est CPU-bound. Ils tournent sur une infrastructure séparée avec des politiques de scaling séparées.

Pré-chauffer, pas auto-scaler. L'auto-scaling est trop lent pour les systèmes en temps réel. Quand une nouvelle instance est prête, le pic peut être terminé. Nous pré-chauffons la capacité en nous basant sur des modèles prédictifs de charge. Le volume de transactions du lundi matin est prévisible. Le Black Friday est prévisible. Pré-chauffer pour le pic attendu, auto-scaler pour l'inattendu.

Délester la charge progressivement. Quand la capacité est vraiment épuisée, passez en mode règles uniquement au niveau du système. L'inférence du modèle est le composant coûteux. Le mode règles uniquement gère 10x le débit avec une qualité décisionnelle légèrement inférieure. C'est le bon compromis quand l'alternative est de rejeter des requêtes.

Ce Que Nous Mesurons

Quatre métriques définissent la santé d'un système décisionnel en temps réel :

  • Latence P99 — Pas la moyenne, pas la médiane. Le 99e percentile. Si 1% des décisions manquent la deadline, ce sont 500 décisions manquées par seconde à 50K de débit.
  • Précision décisionnelle — Mesurée contre une évaluation hors ligne. Comment les décisions en temps réel se comparent-elles aux décisions prises avec une information parfaite et un temps illimité ?
  • Taux de fallback — Quel pourcentage de décisions contourne l'inférence du modèle ? Des taux de fallback en hausse indiquent des problèmes d'infrastructure.
  • Complétude des traces — Quel pourcentage de décisions a des traces d'audit complètes ? Cela doit être 100%. Tout ce qui est en dessous est un risque de conformité.

Quand En Avez-Vous Besoin

Toutes les décisions n'ont pas besoin d'être en temps réel. Le batch processing est plus simple, moins coûteux et parfaitement adéquat pour de nombreux cas d'usage. Construisez un système décisionnel en temps réel quand :

  • Les décisions ont une contrainte de délai (transactions, routage, sécurité)
  • La qualité de la décision se dégrade avec la latence (la meilleure réponse en 5 minutes est pire qu'une bonne réponse en 200ms)
  • Le volume décisionnel rend la revue humaine impossible
  • Les exigences réglementaires imposent la traçabilité des décisions individuelles

Si votre cas d'usage remplit ces critères, l'architecture décrite ici fonctionnera. Nous l'avons éprouvée en production dans plusieurs secteurs.

Si vous n'êtes pas sûrs, parlons-en. La mauvaise architecture pour le mauvais problème coûte plus cher que les deux problèmes réunis.