Rendimiento AJAX

admin-ajax.php va lento y está machacando el servidor

El log de acceso se llena de POST /wp-admin/admin-ajax.php y cada llamada tarda segundos, mientras el frontend sigue yendo bien. Qué carga realmente ese endpoint - y cómo ver qué plugin está detrás.

Por qué un admin-ajax.php lento parece un ataque

admin-ajax.php es el único endpoint AJAX de todo WordPress. Heartbeat, widgets del dashboard, maquetadores, fragmentos del carrito, búsqueda en vivo - cada función interactiva postea a ese mismo archivo en lugar de cargar una página.

Lo caro es el arranque. Cada llamada ejecuta una carga completa de WordPress - plugins_loaded, init, admin_init - dentro del contexto wp-admin, y luego dispara el action hook. Un plugin que quema 400 ms en admin_init paga ese coste en cada llamada que llega, sea cual sea la action que la dispare.

El patrón

La CPU sube y el log de acceso se llena de POST /wp-admin/admin-ajax.php, cada request respondiendo en segundos. El frontend puede seguir yendo bien porque el caché de página lo cubre, mientras cada pestaña del editor abierta añade otro chorro de llamadas al mismo endpoint.

O sea que dos quejas distintas caen sobre el mismo archivo: cada llamada es lenta y las llamadas no paran. Las dos empiezan por la misma pregunta - ¿qué se está ejecutando realmente dentro de esos requests?

Quién sigue llamando a admin-ajax.php

Antes de culpar a una botnet, cuenta los llamantes. Los reincidentes son aburridos:

Llamante Qué hace
Heartbeat El editor de entradas postea a admin-ajax.php aproximadamente cada 15 segundos mientras está abierto. Tres pestañas en la misma entrada son tres chorros de llamadas.
Plugins con polling Dashboards de backups, escáneres de seguridad, widgets de chat y paneles de analítica golpean el endpoint a intervalos, mire alguien o no.
Ajax de frontend Fragmentos de carrito, filtros y handlers de formularios con un hook nopriv también corren para visitantes sin sesión, así que el tráfico real suma su propia carga.
Tu propio handler Cada plugin o theme que registra una action wp_ajax_ comparte el mismo endpoint y el mismo coste de arranque.

La pestaña Network de tu navegador muestra el parámetro action de las llamadas lentas, y el log de acceso muestra la frecuencia. Eso te dice qué chorro es. No te dice por qué las llamadas tardan segundos.

Perfila un request, mira el callback

Saber la action no nombra la causa. Alrededor está todo el stack de plugins - cada callback enganchado a plugins_loaded, init, admin_init y la propia action corre en esa llamada.

Find Slow Callbacks (Pro) perfila una URL de tu sitio. Pega el propio admin-ajax.php - o la página de admin que dispara las llamadas lentas - y lanza un request oculto con tus cookies de admin, mide cada callback por encima del umbral y los ordena por milisegundos con el hook y el archivo de origen.

Como todo el stack de plugins arranca en cada llamada, la tabla de resultados responde dos preguntas a la vez: qué callback hace lenta cada llamada ajax, y cuál solo corrió dentro de tu action. Un plugin que quema 400 ms en admin_init sale arriba - frena cada llamada igual que frena cada página de admin.

Las sesiones se guardan. Perfila, quita o arregla el culpable, vuelve a perfilar - el antes y el después quedan en la misma tabla de historial.

También sirve para el resto de wp-admin

Cualquier URL del mismo sitio se puede perfilar, no solo el endpoint ajax - el mismo request responde a la queja del wp-admin lento cuando las pantallas de admin enteras van a rastras.

Cuando lo lento es una sola query

A veces el callback es una cáscara fina y los segundos viven dentro de una sola query - un lookup de meta sin índice, un table scan en cada poll, una búsqueda con LIKE sobre una tabla grande.

Slow Query Analyzer registra cada query que pasa de su umbral - 0.05 s por defecto - con su llamante, luego ejecuta EXPLAIN sobre cada captura y sugiere un índice listo para ejecutar. admin-ajax.php cuenta como request de admin, así que el modo solo-admin por defecto caza las llamadas ajax sin tocar ningún ajuste.

Los dos leen el mismo request desde extremos distintos. El profiler dice «este callback tardó 4 s»; el analyzer dice «y 3.8 s fue este SELECT en wp_postmeta». Juntos apuntan a un archivo y a una línea de SQL.

¿Conoces el callback y la query? Eso es casi todo el diagnóstico - el arreglo es un parche, un reemplazo o un bug report con los números adjuntos.

Pro desde $79/año →

Lo que los módulos no harán - conviene saberlo antes

  • El profiler envía un GET. No puede repetir el POST exacto que mandó tu navegador, así que un handler que solo lee campos $_POST ve un request vacío y sale pronto. Para esos, perfila la página de admin que dispara la llamada - los callbacks de arranque que comparte cada llamada ajax sí se miden.
  • Un handler protegido con nonce muere primero. Su propio trabajo queda sin medir en el request perfilado; todo lo de alrededor - plugins_loaded, init, admin_init - sí se mide.
  • Se necesita HTTP loopback. El módulo perfila pidiendo tu propio sitio, así que un firewall o hosting que bloquea los requests loopback bloquea también el profiler.
  • Find Slow Callbacks viene apagado por defecto. Instala un profiler MU-plugin, así que lo enciendes cuando lo necesitas - hasta entonces no corre nada.
  • Nada de esto limita Heartbeat ni pone tope al ajax. Los módulos nombran el callback y la query; quitar, reemplazar o reportar al culpable sigue siendo decisión tuya.

FAQ de admin-ajax.php

¿Por qué va admin-ajax.php tan lento en WordPress?

Cada llamada es un bootstrap completo de WordPress más el handler. Un plugin que hace trabajo pesado en init o admin_init frena cada llamada, y una query lenta dentro de un handler hace lo mismo para esa action. El alto volumen de llamadas de Heartbeat y de los plugins con polling multiplica lo que cuesta cada llamada.

¿Es el tráfico de admin-ajax.php un ataque?

Normalmente tu propio admin. El Heartbeat del editor de entradas postea aproximadamente cada 15 segundos por pestaña abierta, y los widgets del dashboard hacen polling a intervalos - en el log de acceso se lee exactamente como un martilleo. Mira el parámetro action de las llamadas; las inundaciones reales existen, pero el fuego amigo es lo común.

¿Puedo simplemente desactivar admin-ajax.php?

No. wp-admin depende de él - autoguardados, actualizaciones, la mayoría de pantallas interactivas - y un montón de frontends también. Bloquear el endpoint cambia un sitio lento por uno roto. Lo que hay que arreglar es el callback lento o el llamante charlatán.

¿La Heartbeat API frena WordPress?

Heartbeat es quien más veces llama dentro de wp-admin, y cada beat es una carga completa de WordPress - en un sitio pesado cada beat paga el coste de arranque entero. Nada en WP Multitool lo limita - el profiler te muestra lo que cuesta cada beat en realidad.

¿Cómo encuentro qué plugin vuelve lento admin-ajax.php?

Dos ángulos. Find Slow Callbacks mide cada callback en un request perfilado y los ordena con hook y archivo de origen, así que nombra el plugin que frena cada llamada. Slow Query Analyzer registra las queries que ejecuta una llamada y marca las que pasan del umbral con sugerencias de EXPLAIN.

¿El profiler repite la llamada ajax que hizo mi navegador?

No - lanza un GET a la URL que le das, con tus cookies de admin. Un handler que necesita campos POST o un nonce válido sale pronto, así que su trabajo queda sin medir mientras el arranque de alrededor sí se mide. Para esos, perfila la página de admin que dispara la llamada.

¿Un plugin de caché arregla un admin-ajax.php lento?

No. Las respuestas ajax son dinámicas y deliberadamente sin caché, así que un caché de página nunca las toca. Cada llamada paga el PHP completo más el handler - por eso la única palanca real es hacer la llamada más barata.

Nombra el callback detrás de cada llamada AJAX

Find Slow Callbacks y Slow Query Analyzer son módulos Pro - $79/año para un sitio, y cada plan de pago incluye los 19 módulos. Enciende el profiler cuando el log de acceso empiece a llenarse.

Consigue Pro - desde $79 al año Guía de admin lento Todos los planes en la página de precios →