Caché y Transients API
Optimiza el tiempo de carga y reduce el consumo de recursos. Utiliza la Transients API para almacenar resultados de consultas pesadas o llamadas a APIs con tiempo de expiración.
En el desarrollo profesional de plugins para WordPress, la optimización del rendimiento es una obligación. A medida que tus proyectos escalan, realizan consultas complejas a la base de datos o consumen APIs externas, el tiempo de respuesta del servidor se vuelve un factor crítico.
En este capítulo desmitificaremos el ecosistema de caché nativo. Aprenderás a diferenciar las capas de caché de página, de objetos y de navegador. Dominarás la Transients API para almacenar resultados pesados de forma temporal y descubrirás cómo implementar estrategias de invalidación precisas mediante código. Prepárate para llevar la eficiencia de tus desarrollos al siguiente nivel.
11.1 Diferencias de caché en WP
El ecosistema de WordPress es inherentemente dinámico: cada vez que un usuario solicita una página, el servidor debe cargar el núcleo, ejecutar decenas de plugins, interpretar el tema activo y realizar múltiples consultas a la base de datos para ensamblar el HTML final. Este proceso, aunque flexible, es costoso en términos de recursos y tiempo. Para mitigar esto, intervienen múltiples capas de caché.
Como desarrollador de plugins, es fundamental comprender dónde y cómo opera cada tipo de caché. Ignorar estas capas es una de las principales causas de "bugs" difíciles de rastrear, como contenido que no se actualiza, nonces de seguridad que caducan prematuramente o scripts que cargan versiones antiguas.
A continuación, analizaremos los principales tipos de caché que afectan a WordPress y cómo impactan en el desarrollo de plugins.
Arquitectura de capas de caché
Para visualizar el flujo de una petición y dónde actúa cada capa de caché, observa el siguiente esquema. Cuando una capa tiene éxito (un "hit"), la petición se devuelve inmediatamente, evitando que las capas inferiores se ejecuten.
TEXT
1. Caché de Página (Page Caching)
La caché de página guarda el resultado final de la ejecución de WordPress, es decir, el HTML estático. Puede estar gestionada por el servidor (como Varnish o FastCGI Cache) o por plugins de WordPress (como WP Rocket o W3 Total Cache).
- Cómo impacta a tu plugin: Si la página está en caché, WordPress no se carga. Ningún archivo de tu plugin se ejecuta, y ganchos como
init,wp, otemplate_redirectson completamente ignorados para esa visita. - Consideraciones de desarrollo: Si tu plugin muestra contenido dinámico basado en el usuario (como un contador de visitas en tiempo real, un carrito de compras o un saludo personalizado), la caché de página mostrará el mismo contenido a todos. Para solucionarlo, debes usar cargas asíncronas mediante AJAX (visto en el Capítulo 9) o la REST API (visto en el Capítulo 13) para actualizar fragmentos del DOM después de que el HTML estático haya cargado.
2. Caché de Objetos (Object Caching)
A diferencia de la caché de página, la caché de objetos no almacena HTML, sino datos: resultados de consultas a la base de datos, arrays complejos o variables que requieren un alto coste de procesamiento. WordPress cuenta con la clase interna WP_Object_Cache.
Existen dos modalidades fundamentales que debes distinguir:
- No persistente (Por defecto): WordPress almacena objetos en memoria solo durante el ciclo de vida de una única petición. Si llamas a
get_post(10)tres veces en el mismo flujo de carga, WordPress solo consultará la base de datos la primera vez; las otras dos las sacará de la memoria RAM de esa petición. Al terminar la carga de la página, esta caché se destruye. - Persistente: Mediante el uso de Drop-ins (
object-cache.php) y tecnologías como Redis o Memcached, la caché de objetos sobrevive entre diferentes peticiones y diferentes usuarios. - Consideraciones de desarrollo: Debes programar asumiendo que un entorno de producción tendrá una caché de objetos persistente. Profundizaremos en cómo interactuar con esta API en la sección 11.4, pero el concepto clave es que nunca debes dar por sentado que una consulta directa a la base de datos te devolverá datos frescos si hay una caché persistente de por medio.
3. Caché de Opcode (Opcode Caching)
PHP es un lenguaje interpretado. En cada petición, el código fuente en texto plano debe ser analizado, compilado a bytecode (Opcode) y luego ejecutado. La caché de Opcode (como Zend OPcache) almacena este código precompilado en la memoria compartida del servidor.
- Impacto en el desarrollo: Generalmente es transparente para ti como desarrollador. El código se ejecuta más rápido. Sin embargo, en entornos de desarrollo muy agresivos, si modificas un archivo
.phpy recargas inmediatamente, podrías no ver los cambios si el OPcache no está configurado para revalidar los timestamps de los archivos a tiempo.
4. Caché de Navegador y Edge (CDN)
Esta caché ocurre fuera del servidor principal. Los navegadores web y las Redes de Entrega de Contenido (CDN) almacenan recursos estáticos como hojas de estilo (.css), scripts (.js), imágenes y fuentes tipográficas.
- Cómo impacta a tu plugin: Si actualizas tu plugin e incluyes un nuevo archivo JavaScript, pero mantienes el mismo nombre de archivo, es muy probable que los usuarios sigan ejecutando la versión antigua que tienen guardada en sus navegadores.
- Consideraciones de desarrollo: Para evitar esto, es obligatorio utilizar correctamente el parámetro de versión en las funciones de encolado (revisadas en el Capítulo 7).
PHP
Tabla Comparativa para Desarrolladores
Para resumir, aquí tienes una tabla de referencia rápida sobre qué debes tener en cuenta según la capa en la que te encuentres operando:
| Capa de Caché | Lo que almacena | Riesgo principal para el plugin | Solución habitual |
|---|---|---|---|
| Página | HTML estático de toda la URL | Lógica PHP ignorada, vistas estancadas para usuarios | Usar AJAX/REST para partes dinámicas |
| Objetos | Datos y variables de PHP | Lectura de datos obsoletos en la BD | Uso correcto de invalidación de caché |
| Navegador | Archivos JS, CSS, imágenes | Errores en la interfaz por JS/CSS antiguo | Versionado dinámico en wp_enqueue_* |
| Base de Datos | Consultas SQL crudas (MySQL) | Rara vez problemático si usas la API de WP | Usar $wpdb correctamente |
11.2 Almacenamiento con Transients
Las consultas complejas a la base de datos y, especialmente, las peticiones a APIs de terceros (como procesar un feed externo o consultar un servicio en la nube) son cuellos de botella clásicos en el rendimiento. Para mitigar este problema, WordPress proporciona la Transients API, un método estandarizado para almacenar datos en caché acompañados de un tiempo de expiración.
En esencia, un transient (transitorio) es muy similar a una opción guardada mediante la Options API, pero con una diferencia vital: tiene fecha de caducidad.
¿Dónde se guardan los Transients?
El comportamiento de la Transients API es inteligente y se adapta al entorno del servidor donde esté instalado tu plugin:
- Sin caché de objetos persistente: Si el servidor es básico, WordPress guarda los transients directamente en la tabla
wp_optionsde la base de datos. Creará dos registros por cada transient: uno para el valor en sí y otro para el timestamp de expiración. - Con caché de objetos persistente: Si el servidor tiene configurado Memcached o Redis (y el correspondiente drop-in
object-cache.php), WordPress no toca la base de datos. Almacenará los transients directamente en la memoria RAM ultrarrápida del servidor, delegando la gestión de la expiración al propio motor de caché.
La regla de oro: Nunca asumas que el Transient existe
Dado que los transients pueden ser almacenados en la memoria RAM y gestionados por sistemas como Redis, pueden desaparecer antes de su fecha de caducidad. Si el servidor necesita liberar memoria, expulsará los transients más antiguos.
Por lo tanto, tu código jamás debe depender de la existencia de un transient para funcionar; siempre debe estar preparado para regenerar los datos si la consulta al transient devuelve false.
TEXT
Funciones principales de la API
La API se compone principalmente de tres funciones increíblemente sencillas de utilizar.
1. Leer un transient: get_transient()
Recibe el nombre del transient y devuelve su valor. Si el transient no existe o ya ha expirado, devuelve estrictamente el booleano false.
Nota de seguridad: Debido a que devuelve false cuando falla, no debes guardar valores booleanos false dentro de un transient, ya que te será imposible distinguir si el valor es realmente false o si el transient simplemente ha expirado. Si necesitas almacenar estados booleanos, utiliza enteros (1 o 0).
2. Guardar un transient: set_transient()
Guarda el valor. Acepta tres parámetros:
$transient(string): Nombre único de la clave (máximo 172 caracteres). Es vital usar prefijos únicos, igual que con las opciones.$value(mixed): El dato a guardar. Puede ser un string, un array o un objeto (WordPress se encarga de serializarlo automáticamente).$expiration(int): El tiempo de vida en segundos.
Constantes de tiempo en WordPress:
Para evitar calcular los segundos mentalmente y hacer tu código más legible, WordPress incluye constantes globales que deberías utilizar siempre en el parámetro $expiration:
MINUTE_IN_SECONDS(60)HOUR_IN_SECONDS(3600)DAY_IN_SECONDS(86400)WEEK_IN_SECONDS(604800)MONTH_IN_SECONDS(2592000)YEAR_IN_SECONDS(31536000)
3. Eliminar un transient: delete_transient()
Borra el transient manualmente antes de que expire. Útil cuando sabes que los datos originales han cambiado y necesitas forzar una actualización (por ejemplo, al guardar un post).
Implementación del Patrón Estándar
El uso correcto de los transients requiere agrupar la comprobación y la generación en un solo bloque lógico. A continuación, se muestra el patrón de diseño definitivo que debes aplicar en tus plugins:
PHP
Transients de Red (Multisite)
Si estás desarrollando para una red Multisite (WPMU) y necesitas que un transient esté disponible para toda la red (en lugar de solo para el sitio específico dentro de la red donde se solicitó), WordPress proporciona una variante de las funciones anteriores:
get_site_transient()set_site_transient()delete_site_transient()
Estas funciones operan exactamente igual, pero si no hay caché de objetos configurada, guardarán los datos en la tabla wp_sitemeta en lugar de wp_options.
11.3 Limpieza e invalidación
Existe una famosa cita en ingeniería de software atribuida a Phil Karlton: "Solo hay dos cosas difíciles en Ciencias de la Computación: la invalidación de caché y nombrar cosas". En el desarrollo de plugins para WordPress, esta afirmación cobra un sentido absoluto.
Dejar que la caché expire por tiempo (como vimos en la sección anterior con los Transients) es una estrategia pasiva. Sin embargo, si tu plugin muestra un listado de "Últimos productos" y el administrador publica uno nuevo, esperar 12 horas a que la caché expire ofrecerá una experiencia de usuario deficiente. Aquí es donde entra la invalidación activa.
La invalidación activa consiste en purgar la caché programáticamente en el momento exacto en que los datos subyacentes cambian, garantizando que los usuarios siempre vean la información fresca sin sacrificar el rendimiento general.
Invalidación basada en Eventos (Hooks)
La arquitectura basada en eventos de WordPress hace que la invalidación de caché sea predecible. Debes identificar qué acciones (Actions) modifican los datos que tienes cacheados y enganchar tus funciones de limpieza a esos puntos específicos.
Supongamos que tienes un transient llamado mi_plugin_lista_posts_destacados. Deberías borrar este transient cada vez que un post se guarde, se actualice o se elimine.
PHP
El problema de la invalidación masiva (y la solución del Versionado)
A diferencia de las consultas SQL, la API de Transients no permite borrar múltiples registros usando comodines (no existe un delete_transient( 'mi_plugin_*' )). Si tu plugin genera cientos de transients dinámicos (por ejemplo, mi_plugin_usuario_1, mi_plugin_usuario_2, etc.), iterar sobre todos ellos para borrarlos es ineficiente y, en entornos con caché de objetos persistente, a menudo imposible sin conocer las claves exactas.
La solución profesional a este problema es el Versionado de Caché.
En lugar de borrar los transients uno por uno, agregas un número de versión global al nombre de la clave del transient. Cuando necesitas invalidar todos los transients de tu plugin a la vez, simplemente incrementas ese número de versión. Los transients antiguos quedarán huérfanos y el motor de caché los expulsará eventualmente cuando expiren o necesite liberar memoria.
TEXT
Implementación en código:
PHP
Limpieza de la Caché de Página de Terceros
Si tu plugin modifica la interfaz visual del front-end (por ejemplo, actualiza un banner global desde tus opciones), limpiar los transients no será suficiente si el sitio utiliza un plugin de caché de página (WP Rocket, W3 Total Cache, LiteSpeed, etc.), ya que estos sirven HTML estático.
Los plugins de caché bien programados escuchan ganchos estándar como clean_post_cache o save_post para limpiar partes de su propia caché. Sin embargo, si tu plugin utiliza tablas personalizadas o configuraciones globales que no disparan estos ganchos nativos, tendrás que invocar la limpieza de página explícitamente.
Para mantener buenas prácticas, nunca asumas que un plugin de terceros está activo. Comprueba si su función de purga existe antes de llamarla:
PHP
El peligro de wp_cache_flush()
Al trabajar con la caché de objetos (que detallaremos en la siguiente sección), existe una función central llamada wp_cache_flush(). Su propósito es vaciar completamente la memoria de la caché de objetos.
Advertencia estricta: Como desarrollador de plugins, **nunca debes llamar a wp_cache_flush() en un entorno de producción como respuesta a una acción del usuario (como guardar una configuración).
Hacerlo no solo borra la caché de tu plugin, sino la de todo el núcleo de WordPress, la de otros plugins y, en servidores compartidos mal configurados (donde Redis/Memcached no aísla por prefijos), podría borrar la caché de otros sitios web alojados en el mismo servidor. El resultado es un pico masivo de CPU y consultas a la base de datos (conocido como Cache Stampede o estampida de caché) que puede tumbar el servidor instantáneamente. Utiliza siempre borrados selectivos o la técnica de versionado.
11.4 Object Cache a nivel de código
La API de Caché de Objetos (Object Cache API) es el motor interno que sustenta gran parte del rendimiento de WordPress. A diferencia de los Transients, que están diseñados para persistir por defecto (ya sea en la base de datos o en memoria), el Object Cache nativo es, en su estado puro, un sistema de almacenamiento en memoria RAM no persistente. Esto significa que los datos viven únicamente durante el ciclo de vida de la petición HTTP actual y se destruyen inmediatamente después de que el script PHP termina su ejecución.
Sin embargo, si el servidor cuenta con un sistema de caché persistente (como Redis o Memcached) y su respectivo archivo drop-in object-cache.php en el directorio /wp-content/, las mismas funciones de esta API pasan automáticamente a almacenar los datos de forma permanente entre peticiones. Tu código como desarrollador de plugins debe escribirse pensando en que el entorno puede cambiar de no persistente a persistente sin previo aviso.
Funciones fundamentales de la API
A nivel de código, interactuamos con la API mediante cuatro funciones principales. Todas ellas comparten una estructura jerárquica basada en una clave ($key) y un grupo ($group).
1. wp_cache_set() y wp_cache_add()
Ambas funciones guardan datos en la memoria, pero su comportamiento ante datos preexistentes es crucialmente distinto:
wp_cache_set( $key, $value, $group = '', $expire = 0 ): Guarda el valor sin importar si la clave ya existe. Si ya existía, sobrescribe el valor anterior.wp_cache_add( $key, $value, $group = '', $expire = 0 ): Solo guarda el valor si la clave no existe previamente. Si la clave ya existe, la función devuelvefalsey no modifica nada. Es ideal para evitar condiciones de carrera (race conditions).
Nota sobre $expire: Al igual que con los transients, se mide en segundos. Si no se utiliza un sistema de caché persistente de terceros, este parámetro se ignora por completo, ya que la memoria se vacía al terminar la petición.
2. wp_cache_get()
wp_cache_get( $key, $group = '', $force = false, &$found = null ): Recupera el valor almacenado bajo esa clave y grupo.
3. wp_cache_delete()
wp_cache_delete( $key, $group = '' ): Elimina de forma inmediata el objeto de la memoria.
El concepto de "Grupos" de Caché
El parámetro $group te permite compartimentar la caché de tu plugin. Evita colisiones de nombres con el núcleo de WordPress o con otros plugins. En lugar de crear una clave kilométrica como mi_plugin_perfil_usuario_42, puedes estructurarlo limpiamente:
PHP
Además, algunos motores de caché persistente como Memcached o Redis aprovechan los grupos para permitir la invalidación o flushing selectivo de un grupo entero, optimizando masivamente la limpieza.
El patrón de verificación estricto: El parámetro $found
Un error crítico y muy común en desarrolladores intermedios es verificar la existencia de un objeto en caché evaluando directamente si el resultado de wp_cache_get() es equivalente a false:
PHP
Si el resultado legítimo de una consulta pesada a la base de datos o a una API es el valor booleano false, un string vacío "" o el entero 0, la comprobación tradicional fallará catastróficamente, obligando a tu plugin a repetir la tarea pesada en cada petición.
Para solucionar esto, WordPress introdujo el cuarto parámetro por referencia llamado $found. Este parámetro se pasará a true si la clave existe en la caché (incluso si su valor es false o null), y a false si realmente hubo un cache miss.
Implementación Profesional del Object Cache
A continuación, se detalla la estructura exacta que debes implementar para envolver operaciones costosas mediante Object Cache utilizando el parámetro $found:
PHP
Cuándo usar Transients vs. Object Cache
Para cerrar la arquitectura de rendimiento de tu plugin, debes memorizar esta distinción técnica:
TEXT
- Usa Transients: Cuando consultes una API externa (como el tiempo meteorológico, cotizaciones, o validación de licencias remota) y necesites que el dato persista por horas de manera garantizada, incluso en el hosting compartido más económico sin Redis.
- Usa Object Cache: Cuando realices consultas SQL personalizadas con
$wpdbdentro del código de tu plugin que puedan repetirse múltiples veces en la misma petición, o para almacenar estructuras de datos en memoria que se beneficien drásticamente si el cliente cuenta con un entorno de alto rendimiento basado en Redis/Memcached.
Resumen del capítulo
En este capítulo hemos dominado las capas de optimización y gestión del rendimiento en el desarrollo de plugins profesionales para WordPress:
- Diferencias de caché en WP: Aprendimos a mapear el ciclo de vida de una petición HTTP y cómo interactúan la caché de página (que bloquea la ejecución de PHP), la caché de objetos (interna de datos), el OPcache (precompilación de scripts) y el versionado de archivos estáticos en el navegador.
- Almacenamiento con Transients: Estudiamos la Transients API como mecanismo de persistencia temporal activa, comprendiendo su almacenamiento adaptativo (tabla
wp_optionso RAM) y el patrón correcto de rescate ante un cache miss. - Limpieza e invalidación: Analizamos las estrategias para mantener la integridad de los datos mediante la purga reactiva ligada a hooks, los peligros globales de
wp_cache_flush()y la técnica avanzada de versionado de claves de caché para invalidaciones masivas instantáneas. - Object Cache a nivel de código: Desgranamos la API interna
WP_Object_Cache, el uso estratégico de los grupos de caché y el patrón de desarrollo imperativo empleando el parámetro de comprobación estricta$foundpor referencia.
© 2026 Esdocu. Contenido bajo licencia MIT.
Editar esta página