Outlined
Retour au blog
Retour d'expérience 20 janvier 2026

Comment on a rendu instantané le calcul de prix sur 300 000 produits avec Elasticsearch

Un extranet B2B avec des millions de combinaisons de prix possibles. La solution classique ne scalait plus. On a tout repensé avec les runtime fields.

Illustration d'optimisation Elasticsearch pour catalogue B2B

Un client nous contacte avec un problème de scaling. Son extranet B2B fonctionne bien… tant qu’il n’y a pas trop de clients. Mais avec l’onboarding de plusieurs centaines de nouveaux comptes prévu, l’architecture actuelle ne tient plus.

Le coupable ? Le système de calcul des prix.

Le contexte : un catalogue B2B complexe

L’extranet gère :

  • +300 000 produits référencés
  • Un ou plusieurs catalogues personnalisés par client
  • Des règles de prix spécifiques par catalogue (remises, majorations, prix fixes…)
  • Des millions de combinaisons possibles quand on croise clients × catalogues × règles

Jusque-là, chaque modification de règle tarifaire déclenchait une réindexation complète des prix concernés dans Elasticsearch.

Résultat : 15 minutes d’attente à chaque changement de prix.

Pour un commercial qui se rend compte d’une erreur de tarif, c’est inacceptable. Et avec des centaines de clients ayant chacun leurs règles, le système passait son temps à réindexer.

La solution : runtime fields + Painless

Plutôt que de stocker les prix calculés, on a inversé l’approche : calculer les prix à la volée au moment de la requête.

Elasticsearch propose les runtime fields : des champs calculés dynamiquement lors de la recherche, sans réindexation.

Comment ça fonctionne

  1. Les données brutes restent simples — Prix de base, identifiants catalogues, règles applicables
  2. Le calcul se fait en Painless — Le langage de scripting d’Elasticsearch applique les règles au moment de la requête
  3. Résultat instantané — Plus besoin de réindexer, le prix est calculé à chaque recherche
{
  "runtime_mappings": {
    "prix_client": {
      "type": "double",
      "script": {
        "source": """
          double prix = doc['prix_base'].value;
          if (doc['remise_catalogue'].size() > 0) {
            prix = prix * (1 - doc['remise_catalogue'].value / 100);
          }
          emit(prix);
        """
      }
    }
  }
}

Les résultats

Le changement est radical : Les commerciaux peuvent désormais corriger une erreur de prix et voir le changement immédiatement et non plus patienter 15 minutes.

Le point de vigilance : les ressources serveur

Les runtime fields ont un coût : le calcul se fait à chaque requête, ce qui consomme du CPU.

Avant de valider cette approche, on a fait des tests de charge avec Grafana K6 pour s’assurer que ça tenait la route en production.

Résultats des tests

Pour nos tests K6, on a simulé un scénario réaliste : 1 requête par seconde par utilisateur. C’est ce qu’on observe en moyenne sur un extranet B2B — un commercial qui navigue dans le catalogue, affine ses filtres, consulte des fiches produits.

Avec ce paramétrage :

  • 200 utilisateurs simultanés = 200 requêtes/seconde en continu
  • Temps de réponse moyen < 300ms sur les recherches catalogue
  • Aucune dégradation notable même après 30 minutes de charge soutenue
  • Infrastructure modeste : ~100€/mois d’hébergement

Ce qui lâche en premier (spoiler : pas Elasticsearch)

On a poussé les tests au-delà des 200 utilisateurs pour voir où ça casse. Surprise : c’est la base de données PostgreSQL qui sature avant Elasticsearch.

Les runtime fields tiennent la charge, mais les requêtes annexes (authentification, récupération du profil client, historique de commandes…) finissent par faire exploser le pool de connexions PostgreSQL.

Bonne nouvelle : ça confirme que notre choix d’architecture est solide. Le goulot d’étranglement n’est plus sur le calcul des prix mais sur des opérations classiques, plus faciles à optimiser (cache, read replicas, etc.).

Et pour la suite ?

Si le client doit absorber encore plus de charge, la prochaine étape sera probablement de clusteriser l’infrastructure : plusieurs nœuds Elasticsearch et des read replicas PostgreSQL. Ça permettrait d’augmenter le nombre maximal d’utilisateurs simultanés tout en améliorant la résilience (failover automatique en cas de panne d’un nœud).

Pour l’instant, l’infrastructure mono-serveur suffit largement. Mais le chemin de scaling est tracé.

Le ratio coût/performance est excellent. On évite une infrastructure complexe avec du cache distribué ou des workers de réindexation.

Quand utiliser cette approche ?

Les runtime fields sont pertinents quand :

  • Les données de base changent fréquemment
  • Le calcul est relativement simple (quelques opérations)
  • Le volume de requêtes reste raisonnable
  • La réindexation est un goulet d’étranglement

Ils sont moins adaptés pour :

  • Des calculs très complexes (agrégations lourdes)
  • Des volumes de requêtes massifs (millions/jour)
  • Des données qui ne changent jamais (autant les pré-calculer)

Ce qu’on en retient

Parfois, la solution n’est pas d’optimiser le processus existant, mais de repenser l’architecture.

Ici, passer d’un modèle “pré-calculé et stocké” à un modèle “calculé à la demande” a résolu le problème de scaling tout en simplifiant l’infrastructure.

Et les commerciaux sont contents. Ça, ça n’a pas de prix.


Vous avez des problèmes de performance sur votre catalogue produits ? On peut auditer votre architecture et proposer des solutions. Parlons-en.

#elasticsearch #performance #b2b #backend #ecommerce

Un projet tech en tête ?

Discutons de vos besoins et voyons comment on peut vous aider.

Prendre contact