Hay un momento por el que pasa toda tienda WooCommerce. Suele ocurrir en torno a los 500.000 € de facturación anual, o con unos pocos miles de productos activos, o durante una campaña de alto tráfico que rompe algo que nadie detectó en el entorno de desarrollo.
La tienda deja de sentirse rápida. Las páginas del carrito tardan tres segundos. El abandono en el proceso de pago se dispara. El proveedor de alojamiento dice «necesitas más recursos» y te presupuesta un plan superior. PageSpeed Insights lo pinta todo de rojo.
Más recursos rara vez solucionan el problema de fondo. Lo que sí lo soluciona: saber dónde se ralentiza WooCommerce específicamente a escala, y cuáles son los siete elementos que casi siempre son los verdaderos culpables.
El patrón
Una tienda WooCommerce pequeña es, en su mayor parte, cacheable. Los visitantes llegan a una página de categoría (en caché), navegan por los productos (en caché), añaden al carrito (a partir de aquí, no cacheable), completan el pago y se van. Las páginas en caché cubren más del 90 % del tráfico, y el flujo no cacheable del carrito y el pago gestiona una pequeña minoría de solicitudes con suficiente rapidez.
A escala, dos cosas cambian. En primer lugar, el catálogo crece: más productos, más variaciones, más términos de taxonomía, consultas más grandes. En segundo lugar, la proporción de tráfico en el carrito y el pago aumenta porque las tasas de conversión son aproximadamente estables y se han añadido ceros al número de visitantes. La parte no cacheable del sitio se convierte en el cuello de botella.
Esto es lo que realmente falla, aproximadamente en el orden en que lo encuentro durante las auditorías.
1. Sobrecarga de wp_options autocargadas
Cada solicitud de WordPress carga en memoria todas las opciones marcadas con autoload = yes en wp_options. En un WordPress por defecto, esto supone unos 200 KB. En una tienda WooCommerce con cinco años de antigüedad y una docena de plugins retirados que nunca limpiaron sus datos, puede llegar a los 30 MB.
Compruébalo con esta consulta SQL:
SELECT option_name, LENGTH(option_value)
FROM wp_options
WHERE autoload = 'yes'
ORDER BY LENGTH(option_value) DESC
LIMIT 30;
Si algún registro entre los 30 primeros supera los 100 KB y no sabes por qué está autocargado, casi con toda seguridad no debería estarlo. Culpables habituales: restos de transients que nunca expiraron, registros de trabajos cron, cachés de API de terceros, datos de migración de plugins abandonados.
Cambiar los peores infractores a autoload = no (o eliminarlos por completo) suele restar entre 100 y 300 ms a cada página no cacheada. Es la mayor mejora de rendimiento en la mayoría de las auditorías de WooCommerce.
2. El desastre de las consultas a wp_postmeta
WooCommerce almacena casi todos los datos de productos —precio, stock, atributos, dimensiones, variaciones— en wp_postmeta. Un producto con 12 variaciones y 8 atributos genera alrededor de 100 filas en wp_postmeta. Un catálogo de 500 productos de este tipo supone 50.000 filas. Un catálogo de 5.000 productos, medio millón.
El índice predeterminado de WordPress en wp_postmeta está sobre (post_id, meta_key). Cubre el patrón «dame los metadatos de este producto». No cubre el patrón típico de WooCommerce «dame todos los productos donde _price esté entre X e Y», lo que obliga a exploraciones completas de la tabla.
WooCommerce 8.2 introdujo las tablas de pedidos personalizadas (HPOS), que traslada los datos de pedidos fuera de wp_postmeta por completo. Actívalo. Para los datos de productos, la mejora proviene de una de estas opciones:
- Un índice adicional:
ALTER TABLE wp_postmeta ADD INDEX (meta_key(32), meta_value(32))— hay que manejarlo con cuidado en tablas de gran tamaño, pero resulta transformador en páginas de categoría con filtros de precio - Mover las claves meta más consultadas (
_price,_stock_status,_sku) a una tabla plana personalizada consultada desde las páginas de categoría
3. Fragmentos del carrito y la sobrecarga AJAX
WooCommerce actualiza el mini-carrito en cada carga de página mediante una llamada AJAX a ?wc-ajax=get_refreshed_fragments. En una página en caché esto significa: la página carga rápido (desde caché), pero inmediatamente lanza una petición AJAX sin caché que ejecuta el arranque completo de WordPress.
En una tienda con mucho tráfico, esta única llamada genera más trabajo PHP sin caché que todas las demás peticiones juntas. En servidores con recursos limitados, es la diferencia entre soportar 1.000 usuarios simultáneos o caerse con 200.
Dos soluciones:
- Deshabilitar los fragmentos por completo en las páginas donde el carrito no es visible (la mayoría de páginas de categoría, blog y páginas de contenido). Un filtro, diez líneas de código.
- Mover el contador del carrito al lado del cliente: leerlo desde una cookie establecida al añadir al carrito y renderizar el mini-carrito solo en las páginas de carrito y pago. Reduce la llamada AJAX a prácticamente cero.
4. Proliferación de plugins en el carrito y el pago
Las páginas de carrito y pago se sirven sin caché en cada petición. Cada plugin que se engancha a woocommerce_init, woocommerce_checkout_process o woocommerce_cart_calculate_fees paga su coste de ejecución completo en estas páginas.
En un sitio WooCommerce típico de 3 años de antigüedad suelo encontrar:
- 3 plugins de carrito abandonado (uno en uso, dos heredados de experimentos anteriores)
- 2 integraciones distintas de seguimiento de conversiones (una configurada por marketing, otra por el desarrollador anterior)
- Un plugin de extensión de cupones que añade 5 consultas por cada cálculo del carrito
- Una calculadora de envíos que llama a una API remota en cada carga de página
La auditoría de plugins en estas dos páginas —qué está instalado, qué sigue en uso activo, qué puede sustituirse por funcionalidad nativa de WooCommerce o una sola línea de código del tema— suele reducir el tiempo de respuesta del carrito y el pago entre un 30 y un 50 %.
5. Caché de objetos, correctamente configurada
El almacenamiento en caché de páginas (Cloudflare, LiteSpeed, WP Rocket) ayuda a las páginas cacheables. El flujo del carrito y el proceso de pago necesitan una caché de objetos — Redis o Memcached — para mantener la velocidad en las páginas no cacheables.
La mayoría de las tiendas no tienen ninguna, o la tienen instalada pero mal configurada: compartida entre varios sitios sin un prefijo de clave adecuado, con un tamaño insuficiente que provoca errores de caché, o con los grupos específicos de WooCommerce (wc_session_id, wc_cart) que en realidad no se están cacheando.
Verifícalo con wp_cache_get_stats() o inspeccionando Redis directamente. Una caché de objetos funcional muestra tasas de aciertos superiores al 90% en una tienda con mucho tráfico. Por debajo de eso, probablemente no estés cacheando nada útil.
6. Deuda de regeneración de imágenes
Cada rediseño cambia los tamaños de imagen que solicita el tema. Las tiendas WooCommerce acumulan decenas de tamaños intermedios por imagen de producto — 300×300 del primer tema, 400×400 del segundo, 600×450 recortado de una campaña.
Los originales suelen estar bien. El problema son los decenas de tamaños obsoletos que siguen sirviéndose porque el marcado aún los referencia, o peor aún, la imagen original sirviéndose a 4× el tamaño mostrado porque el tamaño correcto no existe.
Audita con wp media regenerate después de estandarizar un conjunto de tamaños de imagen coherente en el tema. La entrega en WebP a través de un CDN de imágenes (Cloudinary, Bunny, o un CDN con negociación automática de formato) te permite reducir el peso de las imágenes entre un 30 y un 60% adicional sin tocar los originales.
7. Procesamiento en segundo plano para las tareas pesadas
Por defecto, WooCommerce envía los correos de confirmación de pedido de forma síncrona, durante la solicitud de pago. El cliente espera mientras SMTP negocia la conexión. Si tu integración con el CRM/ERP también está enganchada a woocommerce_thankyou, el cliente espera también por eso. Si algo en esa cadena agota el tiempo de espera, el pedido ya se ha creado pero el cliente ve un error.
Mueve todo lo que no sea crítico para la respuesta a ActionScheduler (el sistema de colas que WooCommerce ya incluye):
- Correos de confirmación y de administración
- Integraciones con CRM, ERP y contabilidad
- Sincronización de inventario con otros canales
- Devolución de datos de analítica a cualquier destino que no sea el píxel de conversión
El tiempo de respuesta del proceso de pago cae de entre 4 y 8 segundos (habitual) a menos de 1,5 segundos (alcanzable). Y una API de terceros lenta deja de poder romper todo el flujo de pago.
El orden de actuación
Si te enfrentas a una tienda lenta y no sabes por dónde empezar, este es el orden que yo seguiría:
- Auditoría de opciones autocargadas (1 hora, la mayor mejora individual)
- Fragmentos del carrito (1 a 2 horas, impacto inmediato en la velocidad percibida)
- Auditoría de plugins en el carrito y el proceso de pago (4 a 8 horas, mejora real y medible)
- Caché de objetos (varía según la configuración del servidor)
- Procesamiento en segundo plano para correos electrónicos e integraciones (8 a 16 horas)
- Regeneración de imágenes y CDN (trabajo en paralelo, no bloquea el resto)
- Índices de postmeta (al final, requiere un entorno de pruebas cuidadoso y un plan de reversión en tablas grandes)
En conjunto, en las tiendas que he auditado, estos siete puntos han logrado de forma sistemática reducir el LCP de 4-6 s a menos de 2 s, duplicar el número de usuarios simultáneos que puede soportar el mismo plan de alojamiento y reducir el abandono del proceso de pago en unos pocos puntos porcentuales — lo que en una tienda de 500 000 € supone ingresos reales.
Ninguno de ellos es misterioso. Son simplemente aspectos que no aparecen en una guía genérica de «cómo acelerar WordPress» porque son específicos de WooCommerce.