Symptôme : un site associatif de documentation technique, avec une base de connaissances de plus de 12 000 articles, est devenu quasiment inaccessible pendant quatorze minutes un mardi après-midi, en pleine consultation par les adhérents. L’équipe technique a d’abord suspecté une attaque ou un pic de trafic inhabituel, avant de découvrir dans les journaux qu’un administrateur avait, au même moment, déclenché manuellement une réindexation complète du moteur de recherche interne du site, suite à une restructuration des catégories menée la veille.
Diagnostic : pourquoi une réindexation complète sature le serveur
Une réindexation complète demande de relire l’intégralité du contenu du site (les 12 000 articles, avec leurs métadonnées et taxonomies), de le retraiter (extraction du texte, calcul de pertinence) et de le renvoyer vers l’index de recherche, que ce soit un moteur auto-hébergé comme Elasticsearch via l’extension ElasticPress, ou une solution embarquée comme Relevanssi qui indexe directement dans MySQL. Sur ce site, l’opération avait été lancée sans découpage, en une seule commande, ce qui a saturé simultanément le CPU (calcul de pertinence), la mémoire (chargement du contenu par lots trop grands) et les connexions à la base de données, sur un serveur par ailleurs dimensionné pour le trafic normal du site, pas pour un pic de traitement de fond aussi intense.

Confirmer la cause avec Query Monitor et les journaux serveur
L’inspection des journaux MySQL a montré un nombre de connexions actives multiplié par six pendant la fenêtre du ralentissement, saturant la limite max_connections configurée, ce qui expliquait les erreurs « Too many connections » ponctuelles remontées côté PHP pour les visiteurs qui tentaient de charger une page pendant l’incident. Query Monitor, activé sur une requête de test en environnement de recette reproduisant la réindexation, a confirmé que chaque lot traité par le processus d’indexation exécutait plusieurs dizaines de requêtes SQL, multipliées par le nombre d’articles traités simultanément dans le lot par défaut de l’extension (200 articles par lot sur cette configuration).
Le correctif : découper en petits lots planifiés hors heures de pointe
Deux changements ont été mis en place. D’abord, la taille des lots de traitement a été réduite de 200 à 25 articles, avec une pause explicite entre chaque lot pour laisser respirer le serveur, plutôt qu’un enchaînement continu.
add_filter( 'relevanssi_index_batch_size', function () {
return 25;
} );
add_action( 'relevanssi_index_batch_done', function () {
sleep( 2 ); // pause de deux secondes entre chaque lot de 25 articles
} );
Ensuite, et surtout, la réindexation complète a été retirée des actions accessibles en un clic depuis l’espace d’administration pendant les heures ouvrées, et remplacée par une tâche planifiée qui ne peut se déclencher qu’en dehors des heures de forte consultation, identifiées à partir des journaux d’accès comme la plage 22 h à 6 h.
add_action( 'demarrer_reindexation_complete', function () {
$heure_actuelle = (int) current_time( 'G' );
if ( $heure_actuelle >= 6 && $heure_actuelle < 22 ) {
WP_CLI::warning( 'Réindexation complète refusée en heures de forte affluence (6h-22h).' );
return;
}
relevanssi_build_index( true );
} );
Un administrateur qui souhaite tout de même relancer une réindexation en journée, pour une urgence justifiée, garde la possibilité de le faire via une commande WP-CLI distincte avec un paramètre explicite de contournement, ce qui laisse une échappatoire tout en rendant le déclenchement accidentel bien plus difficile.
Résultat mesuré
Avec le découpage en lots de 25 articles et une pause de deux secondes, une réindexation complète du même catalogue de 12 000 articles, testée en heures creuses, s'étale sur environ dix-huit minutes au lieu de quatre minutes en configuration agressive, mais sans jamais saturer les connexions MySQL ni provoquer de ralentissement perceptible pour d'éventuels visiteurs présents pendant la fenêtre nocturne. La durée totale de l'opération a donc augmenté, un compromis accepté en échange de l'absence totale d'impact perçu par les visiteurs.
- Une réindexation complète consomme des ressources proportionnelles à la taille du catalogue entier, pas à une fraction de celui-ci.
- Réduire la taille des lots et introduire des pauses limite la saturation continue du serveur.
- Planifier hors heures de pointe reste la protection la plus simple, même une fois le découpage en place.
Une opération qui traite 12 000 contenus d'un coup n'est jamais « juste une tâche de fond » : c'est un pic de charge qui mérite la même prudence qu'un lancement de campagne publicitaire.
Ce que ce correctif ne couvre pas
Cet article ne traite pas le choix du moteur de recherche interne lui-même (Elasticsearch via ElasticPress, SearchWP ou Relevanssi), question tranchée en amont pour ce projet selon des critères de pertinence de résultats et de budget d'hébergement distincts des considérations de performance développées ici.
En résumé
Le découpage en petits lots avec pauses, combiné à une restriction du déclenchement manuel aux heures creuses, a fait passer l'impact perçu d'une réindexation complète de quatorze minutes de site quasiment inaccessible à zéro seconde perceptible pour les visiteurs, au prix d'un allongement de la durée totale de l'opération elle-même, un compromis largement favorable pour un site dont la consultation ne s'arrête jamais vraiment en journée.