Feature Store : quand est-ce vraiment indispensable en production IA ?
Le feature store est devenu un buzzword du MLOps. Chaque conférence IA en parle, chaque plateforme ML en propose un. Mais avez-vous vraiment besoin d'un feature store pour votre projet ? La réponse honnête : probablement pas dans la majorité des cas.
Cet article analyse objectivement les situations où un feature store est indispensable, et celles où il ajoute de la complexité sans valeur réelle.
Ce qu'est réellement un feature store
Un feature store est un système centralisé de stockage et de gestion des features (variables d'entrée) utilisées par les modèles de machine learning. Il résout trois problèmes principaux :
- Réutilisation : partager des features entre plusieurs modèles et équipes
- Cohérence : garantir les mêmes calculs en entraînement et en inférence
- Performance : servir des features en temps réel avec une latence faible
┌─────────────────────────────────────────────────────────┐
│ Feature Store │
├─────────────────┬─────────────────┬─────────────────────┤
│ Offline Store │ Online Store │ Feature Registry │
│ (historique) │ (temps réel) │ (métadonnées) │
├─────────────────┴─────────────────┴─────────────────────┤
│ Transformation Pipeline │
└─────────────────────────────────────────────────────────┘Quand un feature store est indispensable
1. Inférence temps réel avec features complexes
Si votre modèle en production doit :
- Récupérer des features en moins de 10ms
- Combiner des données de plusieurs sources (base clients, historique transactions, données externes)
- Calculer des agrégations en temps réel (moyenne sur 7 jours, count sur 24h)
Exemple concret : Un système de détection de fraude bancaire qui doit décider en 50ms si une transaction est suspecte. Il combine l'historique du client, les patterns de transactions récentes, et des features géographiques.
def get_fraud_features(user_id, transaction):
# Requête DB pour historique (50ms)
history = db.query(f"SELECT * FROM transactions WHERE user={user_id}")
# Calcul agrégations (20ms)
avg_amount_7d = calculate_avg(history, days=7)
tx_count_24h = count_recent(history, hours=24)
# Requête API externe (100ms)
geo_risk = external_api.get_risk_score(transaction.location)
return [avg_amount_7d, tx_count_24h, geo_risk]
# Total : 170ms+ (inacceptable)
def get_fraud_features(user_id, transaction):
features = feature_store.get_online_features(
entity_id=user_id,
features=["avg_amount_7d", "tx_count_24h", "geo_risk_score"]
)
return features
# Total : 5-10ms2. Plusieurs modèles partageant les mêmes features
Quand 3+ modèles utilisent des features communes et que vous voulez éviter :
- La duplication de code de feature engineering
- Les divergences de calcul entre équipes
- La maintenance de N pipelines identiques
Exemple concret : Une plateforme e-commerce avec des modèles de recommandation, de pricing dynamique, et de prédiction de churn, tous utilisant des features client communes.
3. Training-serving skew critique
Le training-serving skew est la différence entre les features utilisées à l'entraînement et celles en production. Un feature store garantit que les mêmes transformations s'appliquent dans les deux contextes.
Symptômes du skew :
- Le modèle performe bien en validation mais mal en production
- Des bugs subtils apparaissent après des mois
- Les métriques de monitoring divergent inexplicablement
@feature_view(
entities=[user],
ttl=timedelta(days=1),
online=True
)
def user_features(transactions: DataFrame) -> DataFrame:
return transactions.groupby("user_id").agg(
avg_amount=("amount", "mean"),
tx_count=("id", "count"),
last_tx_date=("date", "max")
)4. Équipe ML de 5+ personnes
Quand plusieurs data scientists travaillent sur des modèles différents, le feature store devient un contrat d'interface :
- Documentation automatique des features
- Versioning et lineage
- Découverte des features existantes
Quand NE PAS utiliser de feature store
1. Un seul modèle en production
Si vous n'avez qu'un modèle, le feature store ajoute :
- Une infrastructure à maintenir
- Une dépendance externe
- De la complexité pour résoudre un problème que vous n'avez pas
Alternative : Un simple script Python de feature engineering suffit.
def compute_features(raw_data: pd.DataFrame) -> pd.DataFrame:
features = raw_data.copy()
features["amount_normalized"] = features["amount"] / features["amount"].mean()
features["days_since_signup"] = (pd.Timestamp.now() - features["signup_date"]).dt.days
return features2. Inférence batch uniquement
Si votre modèle tourne en batch quotidien ou hebdomadaire, vous n'avez pas besoin d'un online store. Un simple pipeline de données suffit :
def daily_prediction_pipeline():
# 1. Extraire les données
raw_data = spark.read.parquet("s3://data/daily/")
# 2. Calculer les features (même code qu'à l'entraînement)
features = compute_features(raw_data)
# 3. Prédire
predictions = model.predict(features)
# 4. Sauvegarder
predictions.write.parquet("s3://predictions/daily/")3. Features simples sans agrégations temporelles
Si vos features sont :
- Des colonnes directes de votre base de données
- Des transformations simples (normalisation, one-hot encoding)
- Sans agrégations sur des fenêtres temporelles
Le feature store n'apporte aucune valeur. Une requête SQL ou un DataFrame Pandas fait le travail.
4. Prototype ou MVP
En phase d'exploration, validez d'abord la valeur business avant d'investir dans l'infrastructure :
| Phase | Recommandation |
|---|---|
| POC (0-3 mois) | Pas de feature store |
| MVP (3-6 mois) | Pas de feature store |
| Scaling (6-12 mois) | Évaluer le besoin |
| Production mature | Considérer si critères remplis |
5. Budget et équipe limités
Un feature store représente :
- Coût infrastructure : $500-5000/mois selon la solution
- Coût maintenance : 10-20% du temps d'un ML engineer
- Courbe d'apprentissage : 2-4 semaines pour l'équipe
Si vous êtes une équipe de 1-3 personnes avec un budget serré, investissez ailleurs.
Alternatives légères au feature store
Option 1 : Base de données avec cache
class SimpleFeatureService:
def __init__(self):
self.db = PostgresConnection()
self.cache = RedisClient()
self.cache_ttl = 3600 # 1 heure
def get_features(self, user_id: str) -> dict:
# Check cache first
cached = self.cache.get(f"features:{user_id}")
if cached:
return json.loads(cached)
# Compute from DB
features = self.db.query("""
SELECT avg_amount_30d, tx_count_7d, risk_score
FROM user_features WHERE user_id = %s
""", (user_id,))
# Cache for next time
self.cache.setex(f"features:{user_id}", self.cache_ttl, json.dumps(features))
return featuresOption 2 : Table de features pré-calculées
-- Table de features mise à jour par un job batch
CREATE TABLE user_features (
user_id VARCHAR PRIMARY KEY,
avg_amount_30d DECIMAL,
tx_count_7d INTEGER,
last_purchase_days INTEGER,
risk_score DECIMAL,
updated_at TIMESTAMP DEFAULT NOW()
);
-- Job quotidien de mise à jour
INSERT INTO user_features
SELECT
user_id,
AVG(amount) FILTER (WHERE date > NOW() - INTERVAL '30 days'),
COUNT(*) FILTER (WHERE date > NOW() - INTERVAL '7 days'),
EXTRACT(DAY FROM NOW() - MAX(date)),
calculate_risk_score(user_id),
NOW()
FROM transactions
GROUP BY user_id
ON CONFLICT (user_id) DO UPDATE SET ...;Option 3 : Feature engineering dans le modèle
Pour les modèles modernes (transformers, embeddings), intégrez les transformations dans le modèle lui-même :
model = tf.keras.Sequential([
# Preprocessing intégré au modèle
tf.keras.layers.Normalization(),
tf.keras.layers.CategoryEncoding(num_tokens=100),
# Architecture
tf.keras.layers.Dense(128, activation='relu'),
tf.keras.layers.Dense(1, activation='sigmoid')
])Arbre de décision
Avez-vous besoin d'un feature store ?
1. Combien de modèles en production ?
└── 1-2 modèles → Probablement NON
└── 3+ modèles → Continuer
2. Partagent-ils des features communes ?
└── Non → Probablement NON
└── Oui → Continuer
3. Avez-vous des contraintes temps réel (<100ms) ?
└── Non (batch) → Probablement NON
└── Oui → Continuer
4. Vos features nécessitent des agrégations temporelles ?
└── Non (features simples) → Probablement NON
└── Oui → OUI, feature store recommandé
5. Avez-vous les ressources (équipe, budget) ?
└── Non → NON, utilisez une alternative légère
└── Oui → OUI, investissez dans un feature storeSi vous décidez d'en utiliser un
Solutions open source
| Solution | Points forts | Points faibles |
|---|---|---|
| Feast | Simple, bien documenté | Moins de features avancées |
| Hopsworks | Complet, UI incluse | Plus complexe à déployer |
| Tecton (OSS) | Performance | Écosystème plus petit |
Solutions managées
| Solution | Points forts | Coût estimé |
|---|---|---|
| Databricks Feature Store | Intégration Spark | Inclus dans Databricks |
| AWS SageMaker FS | Intégration AWS | $0.20/GB + compute |
| Google Vertex AI FS | Intégration GCP | $0.30/GB + compute |
| Tecton | Performance, temps réel | $2000+/mois |
Critères de choix
- Latence requise : <10ms → Tecton ou solution custom
- Volume de données : >1TB → Solutions cloud managées
- Écosystème existant : AWS → SageMaker, GCP → Vertex, Databricks → leur FS
- Budget : Limité → Feast self-hosted
Conclusion
Le feature store est un outil puissant mais spécialisé. Il résout des problèmes réels de cohérence, réutilisation et performance, mais seulement dans des contextes spécifiques :
Utilisez un feature store si :
- Vous avez 3+ modèles partageant des features
- Vous avez des contraintes temps réel strictes
- Le training-serving skew vous a déjà causé des problèmes
- Vous avez l'équipe et le budget pour le maintenir
N'utilisez PAS de feature store si :
- Vous avez 1-2 modèles
- Vous faites du batch uniquement
- Vos features sont simples
- Vous êtes en phase de prototype
La complexité a un coût. Commencez simple, et ajoutez un feature store quand le besoin devient évident, pas avant.
Pour aller plus loin sur les architectures ML en production, consultez notre article : Feature Store en 2025 : est-ce encore utile en production IA ?