Le WordPress d'aujourd'hui, décodé pour les développeurs

Extensions

Extension réseau à 500 sites : éviter hooks globaux et cache partagé

Une extension réseau pensée pour dix sites ne survit pas toujours au passage à cinq cents. Ce qui casse en premier, et comment concevoir une architecture qui encaisse l'échelle.

Par WordPress Développement • 18 novembre 2022 • 5 min de lecture • Aucun commentaire
Extension réseau à 500 sites : éviter hooks globaux et cache partagé

« Ça fonctionne très bien sur nos dix sites de test » : cette phrase, entendue lors de la revue d’une extension réseau avant son déploiement sur un multisite de cinq cents sites, aurait dû alerter davantage. Une architecture d’extension réseau qui se comporte correctement à dix sites peut s’effondrer très différemment à cinq cents, non pas parce que le code contient un bug, mais parce que certains choix qui n’ont aucun impact mesurable à petite échelle deviennent des goulots d’étranglement sévères une fois multipliés par cinquante.

Le cas le plus révélateur concerne une extension qui synchronisait une table d’options partagées à chaque activation de plugin sur chaque site du réseau, via le hook wpmu_new_blog. Sur dix sites, l’opération passait inaperçue. Sur cinq cents, la création d’un nouveau site du réseau déclenchait cinq cents écritures en cascade dans la table réseau, ralentissant visiblement l’ensemble de l’interface d’administration du réseau pendant plusieurs secondes.

Où se situent les vrais goulots d’étranglement à cette échelle

Trois zones concentrent l’essentiel des problèmes de performance sur un multisite de grande taille : les tables partagées au niveau réseau (wp_sitemeta, wp_blogs), les hooks globaux exécutés systématiquement sur chaque site, et le cache d’objet quand il n’est pas correctement segmenté par site. Une extension conçue sans anticiper ces trois zones fonctionnera à petite échelle et deviendra un problème de performance réseau à mesure que le nombre de sites augmente.

La table wp_sitemeta comme piège classique

Stocker un réglage global d’extension dans wp_sitemeta via update_network_option() est parfaitement adapté à une configuration réseau unique, partagée par tous les sites. Le piège survient quand un développeur y stocke, par erreur d’architecture, des données spécifiques à chaque site individuel sous des clés dynamiques (mon_ext_reglages_site_42), ce qui transforme une table pensée pour un nombre restreint d’entrées globales en une table qui grossit linéairement avec le nombre de sites, ralentissant chaque requête qui la parcourt intégralement.

Éviter les hooks globaux coûteux à la création de site

L'essentiel à retenir : Les tables partagées globales deviennent un goulot d'étranglement à cette échelle ; Un hook global exécuté sur wpmu_new_blog coûte cher multiplié par 500 ; Le cache d'objet doit être groupé par site, jamais partagé sans réflexion

Le hook wpmu_new_blog (ou son équivalent plus récent wp_initialize_site) doit être traité avec une prudence particulière : tout ce qui s’y exécute a un coût multiplié par le rythme de création de nouveaux sites du réseau. Une extension bien conçue à cette échelle différencie l’initialisation strictement nécessaire à la création (créer les tables propres au site, définir les valeurs par défaut minimales) de tout ce qui peut être différé au premier accès réel du site :

add_action( 'wp_initialize_site', function ( WP_Site $site ) {
    switch_to_blog( $site->blog_id );

    // Uniquement le strict nécessaire : pas de synchronisation
    // lourde, pas d'appel API externe à ce stade.
    add_option( 'mon_ext_version_installee', MON_EXT_VERSION );

    restore_current_blog();
}, 10, 1 );

Chaque appel à switch_to_blog() et restore_current_blog() a un coût réel (rechargement du contexte de requêtes, changement de préfixe de table) : sur une boucle qui parcourrait les cinq cents sites du réseau pour une opération d’administration, ces appels répétés peuvent représenter une part significative du temps d’exécution total.

Segmenter le cache d’objet par site

Un cache d’objet persistant (Redis ou Memcached) partagé entre tous les sites du réseau doit isoler ses clés par identifiant de site, faute de quoi deux sites différents peuvent se retrouver à lire ou écraser la valeur en cache l’un de l’autre. WordPress gère cette isolation automatiquement pour les groupes de cache non déclarés comme globaux, mais une extension qui appelle wp_cache_set() avec un groupe personnalisé doit vérifier explicitement que ce groupe n’est pas enregistré par erreur via wp_cache_add_global_groups().

Arborescence type d’une extension réseau pensée pour l’échelle

mon-extension-reseau/
├── mon-extension.php
├── includes/
│   ├── class-reglages-reseau.php   (wp_sitemeta, une seule fois)
│   ├── class-reglages-site.php     (options par site, isolées)
│   ├── class-initialisation-site.php (hooks légers uniquement)
│   └── class-cache-segmente.php
└── admin/
    └── ecran-reseau.php

Ce qui reste hors du périmètre de l’extension

Cette architecture concerne exclusivement la conception de l’extension elle-même. Les questions plus larges de performance générale d’un multisite à cette échelle — configuration serveur, répartition de charge, choix d’un cache d’objet persistant adapté — relèvent d’une réflexion d’infrastructure distincte, qui dépasse le périmètre du code d’une seule extension.

La question à se poser systématiquement avant d’écrire un hook réseau : « que se passe-t-il si ce code s’exécute cinq cents fois d’affilée en quelques secondes ? ». La réponse change souvent radicalement la conception initialement envisagée.

En résumé

Une extension réseau conçue pour un multisite de grande taille doit traiter différemment ce qui est réellement global (réglages réseau uniques) de ce qui est spécifique à chaque site, éviter les hooks globaux coûteux exécutés en boucle, et segmenter correctement son cache d’objet. Ces précautions, invisibles sur un multisite de test à dix sites, deviennent la différence entre une extension qui tient la charge et une extension qui ralentit visiblement l’ensemble du réseau une fois déployée à grande échelle.

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Partager :

À propos de l'auteur

WordPress Développement

Développeur WordPress, passionné par Elementor, le FSE et l’automatisation par IA.

Voir tous ses articles

Dans la même veine

À lire aussi