# Transients qui remplissent wp_options : quand l’API de cache aggrave la lenteur

> Une extension qui stocke des transients sans expiration ou à clés dynamiques finit par saturer wp_options et ralentir chaque requête. Ce qu'on observe et comment nettoyer.

- Auteur : Clément Hadrot
- Publié le : 2022-07-27
- Mis à jour le : 2022-07-27
- Catégorie : Performance
- URL : https://wpmoderne.dev.wordpress-developpement.fr/performance/transients-remplissent-wp-options-aggravent/

## L’essentiel

- Sans backend de cache d'objet persistant, un transient vit dans wp_options
- Une clé dynamique par visiteur ou par session peut créer des milliers d'entrées
- Une expiration absente ou trop longue transforme le transient en fuite lente

Ce qu'on voit : un site de comparateur de prix, sans cache d'objet persistant Redis ni Memcached configuré, voit son temps de réponse se dégrader progressivement sur plusieurs mois, sans qu'aucune modification de code n'ait été déployée entre-temps. Un contrôle de la table `wp_options` révèle plus de 210 000 lignes, contre quelques centaines attendues sur une installation WordPress standard avec une dizaine d'extensions actives.

## Pourquoi c'est un problème

Sans backend de cache d'objet persistant configuré, l'API de transients de WordPress stocke ses données directement dans la table `wp_options`, chaque transient occupant deux lignes : une pour la valeur elle-même, préfixée `_transient_`, une pour son délai d'expiration, préfixée `_transient_timeout_`. C'est un comportement de repli documenté et parfaitement normal en soi.

Le problème apparaît quand une extension construit ses clés de transient de façon dynamique, par exemple en y incluant un identifiant de session ou une combinaison de paramètres de recherche propres à chaque visiteur. Sur ce comparateur de prix, l'extension de recherche à facettes générait une clé de transient différente pour chaque combinaison de filtres sélectionnés par chaque visiteur, avec une expiration réglée à sept jours, jugée trop longue par rapport au volume de combinaisons possibles.

La conséquence directe : la table `wp_options` grossissait de plusieurs centaines de lignes par jour, sans jamais réellement se vider, puisque l'expiration à sept jours laissait largement le temps à de nouvelles combinaisons de s'accumuler avant que les anciennes ne soient éligibles à suppression.

## Pourquoi une table wp_options gonflée ralentit tout

La table `wp_options` joue un rôle particulier dans WordPress : les options marquées `autoload` à `yes` sont chargées en une seule requête à chaque exécution de PHP, dès l'initialisation de WordPress, avant même le traitement de la requête en cours. Si une partie significative des transients ajoutés hérite de cet autoload, chaque page chargée doit désormais transporter en mémoire des dizaines de milliers de lignes inutiles à la requête en cours.

> L'essentiel à retenir : Sans backend de cache d'objet persistant, un transient vit dans wp_options ; Une clé dynamique par visiteur ou par session peut créer des milliers d'entrées ; Une expiration absente ou trop longue transforme le transient en fuite lente

## Quoi faire : diagnostiquer avant de nettoyer

La première étape a consisté à quantifier précisément le problème avec une requête SQL directe, plutôt que de nettoyer à l'aveugle :

```
SELECT COUNT(*), autoload FROM wp_options WHERE option_name LIKE '_transient_%' GROUP BY autoload;
```

Le résultat a confirmé qu'une part importante de ces transients portait bien l'autoload à `yes`, expliquant la dégradation progressive du temps de réponse constatée sur l'ensemble du site, pas seulement sur les pages de recherche à facettes.

## Quoi faire : nettoyer sans casser la fonctionnalité

WP-CLI fournit une commande dédiée à la suppression des transients expirés, à exécuter en premier lieu :

```
wp transient delete --expired
```

Cette commande n'a supprimé qu'une fraction du problème, la majorité des transients n'étant pas encore expirés selon leur délai de sept jours. Un script complémentaire, ciblant spécifiquement le préfixe de clé propre à l'extension de recherche à facettes, a permis de supprimer les entrées les plus anciennes sans toucher aux autres transients légitimes du site :

```
wp db query "DELETE FROM wp_options WHERE option_name LIKE '_transient_facette_%' AND option_id NOT IN (SELECT option_id FROM (SELECT option_id FROM wp_options WHERE option_name LIKE '_transient_facette_%' ORDER BY option_id DESC LIMIT 500) t)"
```

## Quoi faire : corriger la cause plutôt que le symptôme

Le nettoyage ponctuel ne résolvait pas le problème de fond, qui allait recommencer à s'accumuler dès le lendemain. La correction durable a consisté à réduire la durée d'expiration de sept jours à deux heures, jugée largement suffisante pour l'usage réel de cache de résultats de recherche, et à retirer explicitement l'autoload de ces transients via un filtre disponible depuis WordPress 5.4, `pre_wp_unique_id_from_values` n'étant pas concerné ici, mais un simple contrôle du préfixe utilisé lors de l'enregistrement des options concernées.

- Toujours donner une expiration courte et réaliste à un transient dont la clé varie selon le visiteur.
- Vérifier régulièrement la taille de `wp_options` et la répartition de l'autoload sur un site sans cache d'objet persistant.
- Envisager un cache d'objet persistant type Redis dès qu'un site génère un volume important de transients à courte durée de vie.

## Pour aller plus loin

Ce cas ne traite pas la question de l'autoload en général, déjà documentée séparément pour d'autres types d'options : il se concentre spécifiquement sur le cas où l'API de transients elle-même, pourtant conçue pour améliorer la performance, finit par l'aggraver faute d'une conception de clés adaptée au volume réel de combinaisons possibles.
