API Dolibarr : e-commerce Étude de cas orienté performance

Version 1.0 – Novembre 2025


1. Introduction

Dolibarr ERP‑CRM est une solution open‑source très répandée pour gérer les activités commerciales (gestion des devis, factures, stocks, la facturation, le suivi des équipes, etc.). Depuis la version 9, Dolibarr expose une API RESTful (et, depuis la 10, une API JSON‑API plus riche) afin de permettre l’intégration d’applications tierces, la synchronisation avec des plateformes de paiement, des marketplaces ou des solutions de marketing digital.

Cette étude s’attache à démontrer comment exploiter l’API Dolibarr pour augmenter la performance d’une boutique e‑commerce (site vitrine + ERP) en réduisant les temps de réponse, en limitant le load sur la base de données et en assurant la scalabilité sous trafic variable.

Objectif : présenter une architecture, des métriques clés, un scénario de test, les resultados obtenus et les bonnes pratiques permettant de maintenir ou d’améliorer ces performances.


2. Contexte de l’étude

Élément Description
Boutique L’Atelier du Zeste – boutique en ligne spécialisée dans les produits bio et gourmets (≈ 5 000 références, 15 000 clients actifs, catalogue multilingue FR/FR‑EN/ES).
Infrastructure – Serveur d’application : 2 vCPU / 4 Go RAM, Linux Ubuntu‑22.04.
– DB : MySQL 8.0 (InnoDB) + slave de lecture.
– CDN : Cloudfront (images).
– Serveur d’API externe (micro‑service) : 4 vCPU / 8 Go RAM (Node.js).
Charge attendue – Pic : 8 000 requêtes simultanées (Black Friday).
– Trafic moyen : 150 RPS (requêtes par seconde).
Enjeu de performance – Temps moyen de création d’une commande via l’API > 300 ms.
– Latence de consultation du catalogue > 500 ms lors des pics.
– Saturation de la base de données à 85 % du CPU.


3. Architecture du système (API + e‑commerce)

graph LR
A[Front‑end (React/Angular)] -->|HTTPS (REST) | B[API Dolibarr (Gateway)]
B -->|Cache Redis | C[Redis]
B -->|RabbitMQ| D[Queue (Ordres)]
D -->|Consumer| E[Worker PHP (Async)]
B -->|SQL| F[MySQL Primary]
B -->|Read‑only| G[MySQL Replica]
H[Payment Gateway] -->|Webhook| B
I[Marketplace] -->|OAuth2| B

  • API Gateway : point d’entrée unique (/api/), route les requêtes vers des controllers dédiés (Product, Order, Customer).
  • Cache Redis : stocke les réponses publices (listes de produits, prix) pendant 5 min.
  • Queue RabbitMQ : désynchronise les opérations lourdes (création de facture, envoi d’emails, mise à jour de stocks) en mode asynchrone.
  • Worker PHP (Swoole) : processus long qui consomme la queue, évitant ainsi le blocage du thread HTTP.


4. Métriques de performance suivies

Métrique Cible initiale Cible après optimisation
Temps de réponse GET /products?category=... (p95) 500 ms ≤ 150 ms
Création d’une commande (POST /orders) 320 ms ≤ 120 ms
Latence du serveur d’API (CPU) 75 % utilisation ≤ 45 %
Throughput maximal (RPS) 120 RPS ≥ 250 RPS
Erreurs 5xx 3 % < 0.2 %


5. Scénario de charge et résultats

5.1 Configuration du test

  • Outil : k6 (version 0.53) – script load‑test.js générant 1 000 VUs (virtual users) en ramp‑up jusqu’à 2 000 RPS.
  • Durée : 10 min de steady‑state à 2 000 RPS.
  • Payloads :

    • 30 % requêtes catalogue (GET /products).
    • 50 % requêtes commande (POST /orders).
    • 20 % requêtes paiement (POST /payments).

5.2 Résultats : Avant optimisation

Métrique Valeur
Temps moyen de réponse (tempo) 380 ms
p95 620 ms
Erreurs 5xx 2.8 %
Utilisation CPU (API) 78 %
Throughput atteint 1 200 RPS (saturation à 1 300 RPS)

5.3 Résultats : Après optimisation (implémentation des bonnes pratiques, voir § 6)

Métrique Valeur
Temps moyen de réponse (tempo) 132 ms
p95 158 ms
Erreurs 5xx 0.14 %
Utilisation CPU (API) 38 %
Throughput atteint 2 680 RPS (stable jusqu’à 3 200 RPS sans saturation)

Gain de performance : + 108 % de débit, réduction de 58 % du temps de réponse médian, amélioration de la disponibilité (erreur 5xx passant de 2,8 % à 0,14 %).


6. Bonnes pratiques et points d’optimisation appliqués

# Action Impact sur la performance Mise en œuvre
1 Cache HTTP (Redis) des requêtes GET catalogue Réduction de 70 % des appels DB pour les listes de produits. Cache-Control: max-age=300 + ETag géré par le controller.
2 Pagination + paramètres de tri côté client Limite le nombre d’enregistrements renvoyés (max 50 lignes). Paramètres ?page=2&per_page=50&sort=price_asc.
3 Batch INSERT/UPDATE dans les API d’import Passage de 30 ms à 8 ms par 100 lignes d’import de prix. Utilisation de $db->query('INSERT ... VALUES ...') en batch.
4 Mode asynchrone pour les paiements Découple le temps de réponse du paiement (≤ 150 ms). Envoi de l’identifiant de transaction dans une queue RabbitMQ.
5 Utilisation de Swoole (serveur PHP async) Réduction du nombre de processus PHP de 8 à 2, économie de 30 % de RAM. Configuration extension=swoole + daemonize=1.
6 Réplication en lecture (Read‑Only replica) Découpage 60 % du trafic DB vers le replica, réduction de la contention. SELECT ... FROM products FROM replicate_master(); dans le modèle.
7 Compression des réponses (Brotli) Diminution du volume réseau de 35 % pour les réponses JSON. Content-Encoding: br via Nginx.
8 Profilage et tuning du MySQL (innodb_buffer_pool_size = 1 GiB, max_connections = 200) Diminution du temps moyen de requête DB de 12 ms à 4 ms. Modifications du fichier my.cnf et FLUSH TABLES.
9 Limitation du débit (Rate Limiting) Protection du serveur contre les floods, diminution du temps de traitement des requêtes anormales. Token Bucket algoritmo (k6 ou Envoy).
10 Monitoring actif (Prometheus + Grafana) Alertes précoces sur la latence > 200 ms et utilisation CPU > 70 %. Scrape /metrics exposé via php-fpm-exporter.


7. Analyse des gains – Pourquoi ces optimisations fonctionnent

  1. Réduction du nombre de round‑trips DB : Le cache HTTP + la pagination diminuent le nombre de scans de tables.
  2. Déplacement des opérations longues vers le workers : La création de factures ou l’envoi d’emails n’empêche plus le thread HTTP d’attendre, rendant la latency perçue plus basse.
  3. Scalabilité horizontale : La replication de lecture et le workers pool permettent d’ajouter des instances sans changer le code (micro‑services).
  4. Optimisation du pipeline réseau : Compression Brotli + CDN réduit le volume transporté, ce qui accélère le retour perçu côté client.
  5. Allocation de ressources ciblées : Utilisation de CPU‑pinning sur les workers Swoole et num_threads sur MySQL pour éviter le contention des connexions.


8. Guide de mise en œuvre pas‑à‑pas (pour répliquer l’étude)

8.1 Pré‑requis

  • Docker‑Compose ≥ 2.5 (ou Kubernetes)
  • Dolibarr ≥ 10.0 (API activée)
  • Redis 6+, RabbitMQ 3.9+, MySQL 8.0+
  • PHP 8.2 avec extensions pdo_mysql, redis, swoole
  • Certificat TLS (Let’s Encrypt)

8.2 Étape 1 – Activer les modules API

// dolibarr/custom/plugins/your_plugin/api_enabled.php
$conf['main']['api_lib_version'] = '9.0';
$conf['main']['api_access_key'] = 'my-secret-key';

8.3 Étape 2 – Déployer un cache des produits

// src/Controller/ProductsController.php
public function getProducts($request, $response) {
$cacheKey = 'products_' . md5($request->getQueryString());
$cached = $this->redis->get($cacheKey);
if ($cached !== false) {
$response->getBody()->write($cached);
return;
}
$products = $this->product->getList($request->getQueryParams());
$payload = json_encode($products);
$this->redis->setex($cacheKey, 300, $payload); // 5 min
$response->getBody()->write($payload);
}

8.4 Étape 3 – Créer la queue d’ordres

# docker-compose.yml (excerpt)
rabbitmq:
image: rabbitmq:3-management
ports: ["5672:5672", "15672:15672"]

// src/Queue/OrderQueue.php
public function publish(Order $order) {
$msg = [
'order_id' => $order->id,
'customer' => $order->customer_id,
'total' => $order->total,
];
$this->channel->basicPublish('orders', '', json_encode($msg));
}

8.5 Étape 4 – Implémenter le worker asynchrone (Swoole)

# worker.php
use Swoole\Runtime;
Runtime::enableCoroutine();
$worker = new \Dolibarr\Worker\OrderConsumer();
$worker->run();

// Worker/OrderConsumer.php
class OrderConsumer {
public function run() {
while (true) {
$msg = $this->queue->get(); // blocking pop
$this->process($msg);
}
}
private function process(array $msg) {
// logique de facturation, email, stock
}
}

8.6 Étape 5 – Configurer la replication MySQL

-- Sur le master
CREATE USER 'repl'@'%' IDENTIFIED BY 'replPass';
GRANT SELECT ON *.* TO 'repl'@'%';
FLUSH PRIVILEGES;
-- Sur le replica
CHANGE MASTER TO MASTER_HOST='db-master',
MASTER_USER='repl',
MASTER_PASSWORD='replPass',
MASTER_LOG_FILE='mysql-bin.000001',
MASTER_LOG_POS=123;
START SLAVE;

Dans le modèle ProductModel::getList() :

protected function getReadConnection() {
if (rand(1,2)===1) return $this->db->getConnection('replica'); // round‑robin
return $this->db->getConnection('primary');
}

8.7 Étape 6 – Ajouter le rate limiting via Nginx

limit_req_zone $binary_remote_addr zone=api:10m rate=50r/s;
server {
location /api/ {
limit_req zone=api burst=20 nodelay;
...
}
}


9. Risques et limites

Risque Mesure d’atténuation
Cache incohérent (stock vendu alors que le cache est actif) Invalider le cache lors de chaque transaction DB ($this->redis->del($cacheKey)).
Surcharge du worker (burst de commande) Utiliser un pool de workers (scale‑out automatiquement via systemd ou Kubernetes).
Latence réseau entre API et DB replica Placer la replica dans le même VPC / zone de disponibilité que le API.
Débordement de la queue Configurer des alertes RabbitMQ (messages_ready) et activer la dead‑letter.
Coût d’infrastructure Autoscaling des pods (Horizontal Pod Autoscaler) selon les métriques CPU/latence.


10. Conclusion

L’étude montre qu’en combinant caching intelligent, asynchronisme, optimisation du SGBD et déploiement de workers Swoole, il est possible de plus que doubler le débit d’une boutique e‑commerce reposant sur Dolibarr tout en divisant par deux le temps de réponse des appels API critiques.

Les bénéfices observés – réduction de 58 % du p95 latency, hausse de 123 % du throughput maximal et chute de 20× des erreurs serveur – sont directement reliés aux bonnes pratiques présentées ci‑dessus.

Recommandation finale : implémenter ces optimisations dès le sprint 3 du projet, mettre en place un tableau de bord de suivi (Prometheus + Grafana) et programmer des revues de performance toutes les deux semaines afin d’ajuster les paramètres de cache et de scaling en fonction de l’évolution du trafic.


Annexes

  1. Script k6 (load‑test.js) – voir le dépôt GitHub dolibarr-perf-demo/k6.
  2. Configuration Redis (maxmemory‑policy allkeys‑lru).
  3. Benchmark de comparaisons : Dolibarr 9 vs Dolibarr 10 (API JSON‑API) – 15 % de latence en moins sur la version 10.
  4. Liste de contrôle (check‑list) de production – 27 items (sérveur, sécurité, sauvegarde, monitoring).


Document rédigé par l’équipe d’architecture cloud de WebOptimise™, 2025.

Publications similaires