Cuando hablamos de mejorar el rendimiento de una tienda online, es habitual escuchar recomendaciones como “activa la caché de PrestaShop”, “activa caché Magento”, “instala Redis” o “pon Cloudflare”. El problema es que cada una de esas tecnologías actúa en una capa diferente y resuelve problemas diferentes.
Una implementación profesional de sistema de caché para una plataforma eCommerce no consiste en activar todas las cachés que tengamos disponibles, sino en identificar donde se produce el cuello de botella y aplicar la estrategia adecuada en cada capa de caché.
Ahora bien, ¿qué entendemos por capa de caché? Toda aplicación web está construida con una arquitectura propia formada por distintos niveles con información que podemos almacenar temporalmente para no tener que volver a construirlos cada vez que visitas o navegas en dicha aplicación web.
Mi dilatada experiencia me ha hecho distinguir, como mínimo, estas capas de caché:
- Capa de aplicación: Almacena información interna que necesita la aplicación para funcionar más rápidamente. Por ejemplo; la caché propia de PrestaShop/Symfony o la caché propia de Magento.
- Capa de plantillas: Evita recompilar/procesar continuamente las plantillas (aspecto visual). Por ejemplo; la caché Smarty en Prestashop o PHTML en Magento. Hablando en bruto: Evita que el navegador tenga que dibujar la web cada vez que accedes a ella.
- Capa de código: OPCache; almacena el código PHP compilado, reutilizándolo cada vez que el usuario interacciona con la plataforma web.
- Capa de datos: Redis; almacena datos o resultados que queremos recuperar rápidamente. Almacena datos de tal manera que los devuelva al usuario sin tener que acceder a la base de datos.
- Capa HTTP: Varnish; almacena respuestas HTTP completas. Devuelve datos sin tener que llegar a php.
- Capa de distribución: CDN; almacena y distribuye recursos como imágenes, CSS, JavaScript y fuentes. Sirve el contenido desde servidores o nodos (proxis) repartidos geográficamente evitando que cada petición tenga que llegar al servidor de origen.
Cada una de estas capas, en un sistema web profesional de primer nivel ha de ser tratada independiente una de la otra. A continuación te dejo un Plan de Arquitectura de Caché que he diseñado desde mi experiencia y conocimiento.
1. Antes de cachear: medir
Antes de modificar la arquitectura analizaría, como mínimo:
TTFB (Time To First Byte)
El TTFB mide el tiempo desde que el navegador solicita una página hasta que recibe el primer byte del servidor. Si el TTFB es alto, puede indicar que el servidor está tardando demasiado en generar la respuesta.
Puedes medir este valor fácilmente mediante PageSpeed Insights, aunque yo personalmente lo hago desde la consola del pc mediante la siguiente instrucción:
curl -o /dev/null -s -w "TTFB: %{time_starttransfer}s\n" https://aquilawebquequieresmedir.com/
¡ojo! un TTFB bajo no significa necesariamente que la página cargue rápido, porque después todavía tenemos que descargar y procesar HTML, CSS, JavaScript, imágenes, fuentes, etc.
Valor ideal: < 250 ms, valor real aceptable: < 650 ms.
Tiempo total de respuesta
Es, en esencia, cronometrar la experiencia del usuario desde que hace clic en un enlace hasta que la página termina de cargarse por completo.
Puedes medir este valor con PageSpeed Insights, no tiene mucho misterio, aunque hay soluciones bastante más avanzadas como WebPageTest pero en un principio con Insights es más que suficiente.
Valor ideal: < 1 s, valor real aceptable: < 2 – 3.5 s
Consultas SQL lentas
En MySQL/MariaDB, activa el registro de consultar lentas slow_query_log y define un umbral de 2 segundos (por ejemplo) con long_query_time. Después analiza el log con herramientas como mysqldumpslow para resumir las consultas lentas o pt-query-digest para un análisis más detallado. En plataformas como Azure Database for MySQL, puedes usar Log Analytics y paneles de control para visualizar el rendimiento de las consultas.
Valor ideal: 0, valor real aceptable: < 1.5%
Consumo de CPU y Memoria
A día de hoy todos los planes de hosting, ya sean compartidos, VPS, dedicados tienen un monitor de consumo de CPU, sólo necesitamos apuntar valores de consumo de CPU para después proceder al análisis para una arquitectura de Caché, no necesitamos Glances, Kula ni Grafana para esto.
Valor ideal: < 60%, valor real aceptable: < 80%
Procesos PHP-FPM y número de peticiones simultáneas
Para conocer el número de procesos activos, inactivos y la cola de peticiones. En un proyecto profesional de primer nivel lo ideal sería utilizar Prometheus y Grafana pero para un momento ocasional que puedas implementar este plan de Caché es más que suficiente hacerlo mediante curl. Hay que llevar a cabo varios pasos que te invito a chatear con tu IA preferida, ella te guiará seguramente mejor que yo en tu sistema (ordénale a la ia: Usar curl con la página de estado de PHP-FPM).
- Valor ideal: < 70% capacidad, valor real aceptable: < 90% capacidad
- Valor ideal: < 100 - 500, valor real aceptable: < 500 – 1000+
- Valor ideal: < 600 ms, valor real aceptable: < 1.5 ms (tiempo de ejecución php)
Respuestas de APIs externas
Puedes medirlas de varias formas. La más sencilla, desde el servidor, es con curl:
curl -o /dev/null -s -w "Tiempo total: %{time_total}s\n" https://api.ejemplo.com/productos
Si quieres analizar mejor dónde se va el tiempo:
curl -o /dev/null -s -w "DNS: %{time_namelookup}s\nConexión: %{time_connect}s\nTTFB: %{time_starttransfer}s\nTotal: %{time_total}s\n" https://api.ejemplo.com/productos
Para una tienda PrestaShop, lo interesante es medir la llamada desde el propio servidor donde está PrestaShop, porque así sabes cuánto tarda realmente la API externa en responder a tu aplicación.
Por ejemplo, si una API de transporte tarda 1,8 segundos, cada petición de PrestaShop que la espere puede aumentar aproximadamente ese tiempo de respuesta. Ahí ya tienes un candidato claro para caché, asincronía o revisión de la integración.
Valor ideal: < 400 ms, valor real aceptable: < 1.5 s
Número de peticiones a recursos estáticos
En Chrome o Firefox, abre la tienda, pulsa F12, ve a Network / Red, recarga la página con Ctrl + F5 y, desde ahí, puedes filtrar por Img, CSS, JS, Font, etc.; el número de peticiones que aparecen corresponde al número de recursos solicitados.
Valor ideal: < 50, valor real aceptable: < 100
Comportamiento de la tienda bajo carga
Con herramientas como Grafana K6 o Jmeter puedes simular 100, 1000 usuarios simultáneos. Puedes medir tiempo de respuesta, TTFB, errores, peticiones por segundo y consumo de CPU/memoria de PHP-FPM y MySQL.
Valor ideal: 0 errores, valor real aceptable: < 1% errores.
2. Analizar y decidir qué capas de caché utilizar
Una vez obtenidas las métricas anteriores, analizaría dónde se encuentra realmente el cuello de botella y, a partir de ahí, decidiría qué capas de caché necesitamos implementar.
No todas las tiendas necesitan todas las capas. Una tienda pequeña puede funcionar perfectamente con OPCache y la caché de aplicación, mientras que una plataforma eCommerce con un catálogo grande, tráfico internacional y miles de usuarios simultáneos puede necesitar una arquitectura mucho más completa.
Si el TTFB presenta un valor elevado
Analizaría el origen del retraso y estudiaría principalmente caché de aplicación, Redis o Varnish, dependiendo de dónde se produzca el cuello de botella.
Redis lo usaría cuando el cuello de botella está dentro de la aplicación, por ejemplo, PrestaShop necesita consultar repetidamente datos o realizar cálculos que podemos conservar temporalmente en memoria. Así evitamos trabajo y/o consultas repetitivas a la base de datos. En el caso de Prestashop, la caché propia de Prestashop/Symfony determina que datos hay que cachear y Redys los almacena.
Por ejemplo, imagina que la página de producto necesita consultar continuamente el stock disponible de un producto u otros datos que se consulten constantemente: precios, configuraciones, sesiones, resultados de búsquedas, datos de catálogo, etc… Si ese dato se consulta miles de veces, podemos mantenerlo temporalmente en Redis y evitar repetir la consulta a MySQL.
Varnish lo usaría cuando el cuello de botella está en generar la respuesta HTTP completa. Si una página de categoría puede ser igual para muchos usuarios, Varnish puede devolver directamente esa respuesta sin que la petición llegue a PHP/PrestaShop. Pero ojo, en plataformas web donde los datos puedan variar entre usuarios no es recomendable utilizar Varnish a la ligera. Por ejemplo, en un B2B, una categoría que muestra productos con precios diferentes según el cliente no debería servirse indiscriminadamente desde una misma caché HTTP, porque podrías terminar mostrando a un cliente el precio de otro.
Si el tiempo total de respuesta es elevado
Analizaría tanto el procesamiento del servidor como la entrega de recursos y estudiaría Varnish y CDN, además de las capas anteriores si fuese necesario.
Aquí diferenciaría dos parámetros:
- TTFB alto → problema principalmente de servidor/aplicación.
- TTFB bueno pero carga total alta → problema probablemente en recursos/frontend/red.
Es decir, si el TTFB es bueno pero la página tarda en completarse, hay que implementar una capa de distribución CDN y optimizar los recursos. No hay más.
Si existen consultas SQL lentas
Analizaría primero las propias consultas y, cuando sea adecuado, utilizaría Redis para evitar repetir determinadas consultas o cálculos.
Por ejemplo, una consulta que obtiene determinadas características o información de un producto y que se ejecuta miles de veces al día. Si esos datos no cambian continuamente, podemos guardar temporalmente el resultado en Redis y evitar repetir la misma consulta a MySQL.
Ni que decir tiene que esa consulta ha de estar bien diseñada, si por ejemplo le falta un índice, utilizar Redis para ocultar dicho problema es poco profesional.
Si el consumo de CPU es elevado
Revisaría OPCache y la caché de aplicación para evitar procesamiento PHP innecesario.
Si el consumo de memoria o los procesos PHP-FPM son elevados
Estudiaría caché de aplicación, Redis y Varnish para reducir el número de peticiones que necesitan llegar hasta PHP. ¡Ojo con Varnish!
Si existe un número elevado de peticiones a recursos estáticos
Implementaría una CDN para distribuir imágenes, CSS, JavaScript, fuentes y otros recursos.
Por ejemplo, una tienda internacional, con clientes en España, Francia, Portugal, Alemania, etc., puede servir las imágenes, CSS, JavaScript y fuentes desde una CDN con servidores o nodos distribuidos por Europa. Así, un cliente de Alemania podría recibir esos recursos desde un nodo cercano, en lugar de tener que descargarlos siempre desde el servidor de origen en España.
Conclusión
De esta forma, cada capa de caché responde a un problema concreto detectado durante la fase de medición, en lugar de implementar todas las tecnologías disponibles sin saber realmente qué problema estamos solucionando.
En el siguiente post te enseñaré cómo configurar cada sistema de caché.