# Site Editor : un cache segmenté par rôle divise le TTFB en formation en ligne

> 40 000 comptes actifs, des contenus différents selon le rôle, et un thème bloc unique. Retour chiffré sur une stratégie de cache différenciée qui a divisé le temps de réponse moyen.

- Auteur : Clément Hadrot
- Publié le : 2025-01-10
- Mis à jour le : 2025-01-10
- Catégorie : FSE
- URL : https://wpmoderne.dev.wordpress-developpement.fr/fse/cache-par-role-plateforme-elearning-fse/

## L’essentiel

- Un même template affiche un contenu différent selon le rôle
- Le cache objet est segmenté par groupe de rôle plutôt que par utilisateur
- Le TTFB moyen a été divisé par 2,4

40 000 apprenants actifs, trois profils distincts (élève, formateur, administrateur pédagogique), et un seul thème bloc pour servir l'ensemble de la plateforme : voilà le terrain sur lequel s'est posée la question du cache. Un cache trop agressif affiche le mauvais contenu au mauvais rôle. Un cache trop prudent ne sert à rien à cette échelle.

Le template `single-cours.html` du thème bloc affiche, via un bloc de liaison à des données (`block bindings`) et un rendu conditionnel côté PHP, un bouton « Continuer le cours » pour l'élève, un lien « Voir les statistiques » pour le formateur, et un accès aux réglages pour l'administrateur pédagogique. Le HTML change selon `current_user_can()`, ce qui interdit a priori un cache de page classique.

## Le piège du cache par utilisateur

La première tentation, écartée dès les tests de charge, était de mettre en cache une version par utilisateur connecté. Avec 40 000 comptes, cela revient à ne quasiment jamais bénéficier du cache : chaque visiteur génère sa propre entrée, le taux de hit reste proche de zéro, et l'espace mémoire alloué au cache objet explose pour un gain quasi nul.

La solution retenue segmente le cache non pas par utilisateur, mais par groupe de rôle. Puisque le HTML affiché ne dépend que du rôle (et non de données strictement individuelles, gérées à part via des appels REST asynchrones), une seule entrée de cache suffit par combinaison template + rôle.

## Mise en œuvre avec les groupes de cache WordPress

L'implémentation s'appuie sur l'API native de cache objet, en définissant une clé de cache qui intègre le rôle principal de l'utilisateur plutôt que son identifiant :

> L'essentiel à retenir : Un même template affiche un contenu différent selon le rôle ; Le cache objet est segmenté par groupe de rôle plutôt que par utilisateur ; Le TTFB moyen a été divisé par 2,4

```
function clef_cache_template( $template_slug ) {
    $user  = wp_get_current_user();
    $roles = $user->roles ? $user->roles[0] : 'visiteur';
    return "tpl_{$template_slug}_{$roles}";
}

function rendu_template_avec_cache( $template_slug ) {
    $clef = clef_cache_template( $template_slug );
    $html = wp_cache_get( $clef, 'templates_role' );

    if ( false === $html ) {
        ob_start();
        include get_stylesheet_directory() . "/templates/{$template_slug}.php";
        $html = ob_get_clean();
        wp_cache_set( $clef, $html, 'templates_role', 15 * MINUTE_IN_SECONDS );
    }

    echo $html;
}
```

Le groupe de cache `templates_role` est déclaré comme groupe non persistant sur les sections réellement dynamiques (statistiques individuelles de progression), et persistant côté Redis pour la structure de page qui ne dépend que du rôle. Cette séparation évite qu'une donnée strictement personnelle (le pourcentage d'avancement d'un élève) ne se retrouve figée dans une entrée partagée.

## Les données individuelles restent hors cache de page

Le pourcentage d'avancement, le badge de dernière connexion ou le nom affiché ne sont jamais mis en cache au niveau du template : ils sont chargés après coup via un point de terminaison REST personnalisé, appelé en JavaScript une fois le HTML statique affiché. Cette séparation entre coquille de page (mise en cache par rôle) et données individuelles (toujours fraîches) est la clé de voûte de toute la stratégie.

### Durée de vie différenciée selon le rôle

Les templates destinés aux élèves, très consultés et peu volatils, gardent une durée de vie de quinze minutes. Ceux destinés aux administrateurs pédagogiques, modifiés plus fréquemment (ajout de cours, changement de statut), descendent à trois minutes, un compromis jugé acceptable au regard de leur volume de trafic beaucoup plus faible.

## Résultats mesurés après trois mois

| Indicateur | Avant | Après |
| --- | --- | --- |
| TTFB moyen (rôle élève) | 780 ms | 320 ms |
| Taux de hit du cache objet | 12 % | 76 % |
| Charge moyenne serveur PHP-FPM | 68 % | 31 % |

Le taux de hit du cache objet est passé de 12 % à 76 % dès la première semaine, grâce à la mutualisation des entrées par rôle plutôt que par compte. Le TTFB moyen a été divisé par 2,4 sur les pages de cours, principalement consultées par le rôle élève, largement majoritaire dans la base d'utilisateurs.

> Sur une plateforme à fort volume d'utilisateurs mais à faible variété de rôles, segmenter le cache par rôle plutôt que par compte individuel change tout : c'est le nombre de combinaisons possibles qui détermine l'efficacité du cache, pas le nombre d'utilisateurs.

## En résumé

Le réflexe consistant à désactiver tout cache dès qu'un contenu dépend de l'utilisateur connecté est souvent excessif. Quand la variation réelle se limite à quelques rôles, une segmentation fine du cache objet permet de conserver les bénéfices de performance sans jamais exposer le mauvais contenu au mauvais visiteur. La discipline à tenir est simple : tout ce qui dépend strictement du rôle peut être mis en cache, tout ce qui dépend de l'individu doit rester dynamique.
