El orden de invalidación de cachés en WordPress + Cloudflare que NO te explican
Cómo purgar 5 capas de caché en WordPress (OPcache, Object Cache, WP Rocket, LiteSpeed, Cloudflare) sin servir contenido viejo. Orden exacto.
Resumen
- El problema: WordPress de hoy tiene 5 capas de caché apiladas (OPcache, Object Cache, WP Rocket, LiteSpeed, Cloudflare). Si las purgas en el orden incorrecto, sigues sirviendo contenido viejo a tus usuarios y a Googlebot.
- La regla: purga de dentro hacia fuera, siempre. OPcache → Object Cache → WP Rocket → LiteSpeed → Cloudflare → (browser, que ya no controlas).
- El error típico: purgas Cloudflare primero. Cloudflare hace fetch al origen, encuentra contenido viejo de WP Rocket, lo cachea de nuevo y vuelves al punto de partida.
- El truco práctico: automatizar el orden con un mu-plugin (must-use plugin) de WordPress que escucha el evento `save_post` y purga en cadena.
- El caso real: un sitio nuestro que servía un H1 antiguo durante 4 horas tras un cambio, hasta que entendimos esto.
Esta es la historia de cómo un cliente nos llamó histérico un sábado porque “el H1 de la home seguía siendo el viejo después de cuatro horas y de purgar el caché”. Por las prisas del cambio, una capa de caché por debajo seguía sirviendo lo viejo. Después de aquel día escribimos esta nota que llevamos años aplicando.
WordPress moderno tiene 5 capas de caché apiladas. Si las purgas en el orden incorrecto, una capa “más arriba” recachea contenido viejo desde una capa “más abajo” que aún no has limpiado. Es contraintuitivo. Y es lo que rompe deploys cada semana.
Las 5 capas, de más cerca a más lejos del origen
Visualízalo como una cebolla. El origen (tu PHP + MySQL) está dentro. La petición del usuario entra desde fuera y, antes de llegar al origen, atraviesa cada capa. Si encuentra una versión cacheada por el camino, la respuesta se sirve desde ahí sin tocar el origen.
Capa 5 (la más interna) — OPcache + Object Cache
OPcache es bytecode PHP precompilado. Cuando un visitante carga una página y PHP necesita ejecutarse, OPcache evita reinterpretar el código fuente desde cero. Acelera entre 2× y 5× cualquier ejecución de PHP.
Object Cache (normalmente Redis o Memcached) cachea queries de la base de datos. Cada llamada WP_Query, cada get_post(), cada get_option() que ya ejecutaste, queda en RAM. Bajada típica: 50-70 % menos consultas a MySQL.
Cachés vivos en RAM del servidor. No conocen el HTML que sale. Son la base.
Capa 4 — WP Rocket (o plugin equivalente)
WP Rocket genera HTML estático precompilado para cada página de tu WordPress. Cuando llega una petición, en vez de ejecutar PHP, sirve un archivo HTML ya hecho que está en disco (wp-content/cache/wp-rocket/).
Plugin a nivel WordPress. Conoce posts, taxonomías, idioma.
Alternativas equivalentes: LiteSpeed Cache plugin, W3 Total Cache, FlyingPress, WP Super Cache.
Capa 3 — LiteSpeed Web Server (LSWS)
Si tu hosting usa LiteSpeed Web Server como servidor web (en vez de Apache o Nginx), LSWS tiene su propio caché a nivel servidor, no a nivel WordPress.
Es más rápido que WP Rocket porque LSWS sirve la respuesta cacheada sin levantar PHP-FPM. Pero solo aplica si tu hosting es LiteSpeed. Si estás en Nginx + PHP-FPM puro, esta capa no existe (la equivalencia sería Nginx FastCGI cache, otro mundo).
Capa 2 — Cloudflare (edge global)
Cloudflare cachea tu HTML en sus 200+ POPs (puntos de presencia) repartidos por el planeta. Cuando un usuario de Tokio pide tu página, no llega a tu servidor en Madrid — llega al POP de Tokio, que tiene una copia cacheada.
Para WordPress, lo razonable es activar Cache Everything (vía Page Rule o Cache Rule) en URLs públicas, excluyendo /wp-admin/ y /wp-login.php.
Capa 1 (la más externa) — Navegador del usuario
Tu navegador cachea según las cabeceras HTTP que envías:
Cache-Control: public, max-age=31536000, immutable→ cachea 1 año, no revalida. Para assets versionados (CSS, JS con hash en el nombre).Cache-Control: no-cache→ cachea pero revalida cada vez con ETag. Para HTML.- Sin
Cache-Control→ comportamiento por defecto del navegador (impredecible). Mal.
No controlas directamente el caché del usuario. Pero puedes empujar la revalidación enviando ETags correctos y respondiendo 304 cuando no haya cambios.
El orden de purga: de dentro hacia fuera
Aquí está la regla en piedra:
1. OPcache (solo si despliegas código nuevo)
2. Object Cache (solo si invalidas algo a nivel queries)
3. WP Rocket (HTML estático del plugin)
4. LiteSpeed (caché del servidor)
5. Cloudflare (edge global)
6. Browser (ya no controlas, pero las cabeceras ya van bien)
Si purgas Cloudflare primero, Cloudflare hace fetch al origen para repoblar su caché → encuentra que LiteSpeed y WP Rocket aún tienen el HTML viejo → cachea ese HTML viejo → has gastado un purge para nada y sigues sirviendo viejo.
Si purgas Object Cache antes de WP Rocket, WP Rocket sigue sirviendo HTML viejo que se generó con queries que ya cambiaron. Otra purga inútil.
Caso real: cómo se nos rompió
Cambio aparentemente inocente: actualizamos el H1 de la home en un sitio cliente. Cliente publica, ve los cambios desde el editor (que va sin caché), todo bien.
Al día siguiente: usuarios y herramientas externas siguen viendo el H1 viejo. Llamada a soporte: “no carga lo nuevo”.
Lo que pasó:
- WP Rocket tenía el HTML viejo en
wp-content/cache/wp-rocket/. El plugin tiene un hook que purga alsave_post, pero alguien había excluido la home del auto-purge tiempo atrás. - LiteSpeed tenía la versión vieja en RAM. Su auto-purge depende de que WP Rocket o el
litespeed-cacheplugin le envíe una señal — que no llegó. - Cloudflare tenía la versión vieja en el edge. Edge cache TTL = 1 hora, pero el cliente había acostumbrado al edge a no fallar nunca.
Lo arreglamos manualmente:
1. wp cache flush (Object Cache → Redis)
2. wp rocket clean (WP Rocket → HTML estático)
3. LiteSpeed Cache → Purge ALL (panel hosting)
4. Cloudflare → Purge Everything (panel CF)
Cuatro purgas seguidas en el orden correcto. Tres minutos después, el H1 nuevo era visible globalmente.
La automatización: un mu-plugin que escucha eventos
Para no repetir esta secuencia manualmente cada vez que el cliente edita un post, escribimos un mu-plugin (must-use plugin: un PHP que WordPress carga siempre, sin que esté en la lista activable de plugins). Vive en wp-content/mu-plugins/cache-purge-chain.php.
Lo que hace, simplificado:
<?php
add_action('save_post', function ($post_id) {
// 1. Object Cache
wp_cache_flush();
// 2. WP Rocket
if (function_exists('rocket_clean_post')) {
rocket_clean_post($post_id);
}
// 3. LiteSpeed Cache
if (defined('LSCWP_V')) {
do_action('litespeed_purge_post', $post_id);
}
// 4. Cloudflare (vía API REST)
purge_cloudflare_url(get_permalink($post_id));
}, 99, 1);
La función purge_cloudflare_url() llama a la API de Cloudflare con un token de API limitado a purge cache para esa zona. Importante: NO purgar todo Cloudflare en cada save_post — cuesta un purge del cupo gratuito (1000/día). Purga solo la URL afectada.
Una advertencia importante: un mu-plugin no debe llevar JS ni CSS de layout. Hace tiempo metimos código de presentación dentro y se rompió un sitio entero. Mu-plugins son para lógica server-side y nada más.
Cuándo purga global vs purga selectiva
| Cambio | Purga |
|---|---|
| Edición de un post / página | Selectiva (solo esa URL) |
| Nuevo menú o widget en sidebar | Selectiva (URLs afectadas) |
| Cambio de tema | Global (todo) |
| Nuevo plugin que afecta a varias páginas | Global |
| Actualización de WordPress core | Global |
| Deploy de código PHP | Global + OPcache reset |
| Cambio en CSS/JS críticos | Global + bumpear versión querystring |
La purga global es cara: tras hacerla, el primer hit a cada URL fuerza recompilado completo de la pipeline (PHP → HTML → caché). Si tu sitio tiene 10.000 URLs, los primeros 10.000 hits van lentos. Reserva para cambios estructurales.
Lo que no se ve: TTL apropiados
La estrategia complementaria al purge es el TTL (Time To Live: cuánto vive una entrada en caché antes de expirar sola, sin necesidad de purge).
Mis recomendaciones para WordPress:
- OPcache:
opcache.revalidate_freq=60(revalida cada 60s en producción, 0 en dev). - Object Cache: TTL por defecto 1 hora, fragmentos críticos 5 min.
- WP Rocket: TTL 10 horas (cubre la jornada de un usuario activo).
- LiteSpeed: TTL 1 día (purga manual cuando hay cambio).
- Cloudflare: Edge Cache TTL 4 horas para HTML, 1 año para assets versionados (CSS, JS, imágenes con hash).
- Browser Cache:
Cache-Control: no-cachepara HTML (siempre revalida con ETag),max-age=31536000, immutablepara assets versionados.
Con esos TTLs + purge automático en save_post cubres el 99 % de los casos sin tener que entrar a panel a purgar manualmente.
Lo que SeoNova hace por ti
Toda esta gestión de capas de caché está dentro del WPO Toolkit que estamos empaquetando en SeoNova: instalas el plugin, conecta tus credenciales Cloudflare + LiteSpeed + WP Rocket, y el sistema purga en orden correcto cada vez que editas algo. Sin escribir mu-plugins, sin gestionar API tokens, sin orden mental que recordar.
Si te interesa, únete a la waitlist con 50 % de descuento durante los 3 primeros meses. Lanzamos en otoño 2026.
Preguntas frecuentes
Las dudas que más nos llegan sobre este tema
¿Por qué tantas capas de caché si en teoría sobra con una?
¿No basta con purgar Cloudflare?
¿Qué pasa con el caché del navegador del usuario?
¿Y si solo cambio un widget del footer en una sola página? ¿Purgo todo?
¿OPcache también hay que purgar?
Sigue leyendo
Más posts del blog que te pueden interesar
- Seguridad WordPress
Cloudflare gratis: cómo darle de alta y 5 reglas anti-bots para tu WordPress
Por qué Cloudflare free es brutal, cómo darle de alta paso a paso y 5 reglas WAF que bloquean el 60-70% de los bots maliciosos sin pagar nada.
9 min de lectura - Seguridad WordPress
Application Passwords en WordPress: ventajas, riesgos y cómo crearlas paso a paso
Qué son las Application Passwords de WordPress, cuándo usarlas, riesgos y guía paso a paso para crear y revocar una sin tocar tu password principal.
7 min de lectura - SEO Técnico
Por qué Google no te indexa: la culpa la tienen los bots (y cómo arreglarlo)
Tu hosting está saturado de bots maliciosos comiéndote el crawl budget. Por eso Googlebot reduce su frecuencia de visita. Datos reales y solución en 30 min.
8 min de lectura