Module 3 — Magasin hors ligne et magasin en ligne
Un magasin de variables héberge deux backends radicalement différents. C'est déroutant au premier abord — on a l'habitude de choisir une base de données, pas deux. Ce module explique pourquoi il en faut deux, ce que chacun stocke, comment on les garde synchrones, et sur quelles technologies les projeter dans le monde réel.
Deux charges de travail, deux formes
Reprenons le scoreur de fraude. À l'entraînement, on veut reconstituer l'état du porteur pour chacun des 40 millions de paiements du dernier trimestre. On lit donc, séquentiellement, 40 millions de lignes de sept variables — soit environ 2 Go de données scannées, en analyse pure : peu de lignes lues par appel, beaucoup d'appels agrégés en un seul balayage massif.
En production, la charge est l'inverse. Le microservice de scoring reçoit une transaction et doit obtenir les sept variables du porteur concerné en moins de 10 ms. Une seule ligne à lire, très fréquemment (des milliers de fois par seconde), et le temps de réponse au 99ᵉ percentile est ce qui compte.
Aucune base de données n'excelle dans les deux régimes. Un entrepôt colonnaire comme BigQuery lit un balayage de milliards de lignes en secondes, mais son plus petit point d'entrée coûte 100 ms — inutilisable pour l'inférence. Un stockage clé-valeur comme Redis répond en 1 ms mais s'écroule dès qu'on lui demande une agrégation sur l'historique complet. La solution industrielle a donc convergé vers deux magasins spécialisés.
Le magasin hors ligne
Ce qu'il contient. L'historique complet, indexé par entité et horodatage. Pour chaque (card_id_hash, event_timestamp), on retrouve la valeur des variables telle qu'elle aurait été observable à ce moment précis. Le module 5 revient longuement sur cette clause.
Ce qu'il sert. Trois usages : l'entraînement (construire la table d'apprentissage), le réentraînement périodique, et l'analyse post mortem (comprendre pourquoi le modèle a raté un cas particulier).
Technologies typiques.
- Cloud gérés : BigQuery, Snowflake, Redshift, Databricks Delta Lake.
- Ouverts sur disque : Parquet sur S3/GCS, avec un moteur comme
DuckDB, Trino ou Spark pour la lecture.
Ordres de grandeur. Volumes typiques : de quelques Go à plusieurs To. Latence acceptable pour une requête complète : quelques secondes à quelques minutes. Coût dominant : le stockage colonnaire (moins de 20 $/To/mois sur S3) et le calcul à la lecture.
Le magasin en ligne
Ce qu'il contient. Pour chaque entité, la dernière valeur connue de chaque variable — pas l'historique. Le porteur card_id_hash=abcd1234 a une seule ligne, avec nb_transactions_1h=3, nb_transactions_24h=17, mise à jour à chaque matérialisation.
Ce qu'il sert. L'inférence en production. Une seule API compte : get(entity_key) → dict de variables.
Technologies typiques.
- Clé-valeur en mémoire : Redis (le plus fréquent), Memcached.
- Bases distribuées : DynamoDB (AWS), Bigtable (GCP), Cassandra, ScyllaDB.
- Nouveaux venus : Vespa, Aerospike pour les très gros volumes à basse latence.
Ordres de grandeur. Volume : quelques Go pour des millions d'entités (une seule ligne par entité, quelques dizaines de variables). Latence cible : 1 à 10 ms au 99ᵉ percentile. Coût dominant : la mémoire, chère (Redis est facturé au Go de RAM).
Comment les deux restent cohérents
Un magasin sans lien entre ses deux backends est un magasin cassé — on retomberait sur l'écart entraînement-service. Trois mécanismes assurent la cohérence.
1. Une définition unique. La vue de variable est écrite une seule fois dans le registre. Le moteur de calcul lit la même expression pour alimenter les deux magasins. Aucune reprise de code entre SQL et un service Java.
2. La matérialisation. À intervalle régulier (ou en continu, pour les variables en flux), un job lit la source, calcule la valeur de la variable pour chaque entité, écrit dans le hors ligne un point historique daté, et écrit dans l'en ligne l'écrasement de la ligne courante. Le module 6 y consacre son entière attention.
3. Le contrôle de cohérence. Un test d'intégration compare, sur un échantillon d'entités, la lecture en ligne à la lecture hors ligne au dernier point matérialisé. Si l'écart dépasse un seuil (0,1 % de désaccord, par exemple), une alerte se déclenche. Sans ce contrôle, la dérive peut s'installer discrètement pendant des semaines.
Pièges classiques
- Recalcul en direct. L'équipe, pressée, code une variable directement dans le microservice de scoring en attendant la matérialisation. La dérive revient par la fenêtre. Règle : ce qui n'est pas dans le magasin n'est pas une variable de production.
- Fréquences non alignées. Le magasin hors ligne est matérialisé toutes les 24 h, l'en ligne toutes les 5 minutes. À l'entraînement, la valeur est retardée d'un jour ; en production, elle est à 5 minutes près. Le modèle apprend à ignorer la fraîcheur, puis s'appuie dessus en production. Piège subtil, décelable seulement par un contrôle de cohérence.
- Explosion du volume en ligne. Ranger l'historique dans Redis fait mécaniquement exploser le coût. L'en ligne stocke une ligne par entité, pas une ligne par événement.
Un magasin en ligne qui contient plus d'une ligne par entité par variable est mal configuré. C'est le symptôme le plus visible d'une confusion entre les deux backends.
En résumé
- Deux charges opposées imposent deux backends : entrepôt colonnaire hors ligne, clé-valeur en ligne.
- Le magasin hors ligne conserve l'historique daté ; il sert à l'entraînement et à l'analyse.
- Le magasin en ligne conserve la dernière valeur par entité ; il sert l'inférence en 1 à 10 ms.
- La cohérence tient à trois choses : définition unique, matérialisation commune et contrôle de désaccord régulier.
Module suivant : comment définir une variable et faire évoluer sa définition sans casser les modèles déjà en production.