Saltar al contenido
← Blog
Blog · Seguridad WordPress

Query Monitor: guía completa para desarrolladores WordPress

WordPressPluginsPerformance

Query Monitor es el panel de herramientas de desarrollo para WordPress y WooCommerce: te muestra qué pasó exactamente en cada carga de página — consultas SQL, hooks disparados, errores PHP, llamadas HTTP, bloques, scripts enqueueados y mucho más. No es “un plugin más de optimización”: es la herramienta de observabilidad que usás cuando un sitio anda lento o rompe y no sabés por dónde empezar.

TL;DR: Query Monitor te dice, para cada carga de página, qué consultas SQL se ejecutaron (y quién las llamó), qué hooks se dispararon, qué errores PHP hubo y dónde se fue el tiempo. Se instala como cualquier plugin, requiere PHP 7.4+ y WP 6.2+, y la versión actual (4.0.7) agrega una vista de timeline. Si sos desarrollador o mantenés sitios WordPress, es la herramienta que te saca del “reinicio a ver si se arregla” y te lleva al “esto es exactamente lo que pasó”.

Lo que hace especial a Query Monitor es cómo presenta la información: agrega las consultas a la base de datos por plugin, tema o función responsable, así sabés en segundos qué componente está generando el problema, en vez de mirar una lista interminable de queries. Y el panel de timeline de la versión 4 muestra todos los eventos de la página en una línea de tiempo, para ver de un vistazo dónde se fue el tiempo.

En esta guía completa vas a encontrar la instalación, cada panel explicado, profiling y logging con código real, constantes de configuración, y el workflow para diagnosticar un sitio lento.

Índice

  1. Qué es Query Monitor y qué muestra
  2. Instalación y el drop-in db.php
  3. Visibilidad: quién puede ver la información
  4. La barra de herramientas: los 4 números
  5. Los paneles uno por uno
  6. Timeline: la novedad de la versión 4
  7. Database Queries: el corazón del plugin
  8. Profiling y logging con código
  9. Assertions para tus propias funciones
  10. Constantes de configuración (wp-config.php)
  11. Workflow: diagnosticar un sitio lento
  12. Query Monitor en producción: qué sí y qué no
  13. Framework, seguridad y add-ons
  14. Qué hacer ahora
  15. Fuentes

Qué es Query Monitor y qué muestra

Query Monitor es el “dev tools panel” de WordPress, mantenido por John Blackbourn y usado en más de 200.000 instalaciones activas. Es software libre, privado por defecto: no almacena datos de forma persistente y no envía nada a terceros.

Para cada carga de página te muestra:

  • Consultas a la base de datos, con alertas de queries lentas, duplicadas o con errores. Podés filtrar por tipo (SELECT, UPDATE, DELETE), por componente responsable (plugin, tema, core) y por función que llama, y hay vistas agregadas por cada uno.
  • El archivo de template usado, la jerarquía de templates completa y las template parts cargadas o no cargadas (temas clásicos y de bloques).
  • Errores PHP presentados con su componente responsable y call stack, con un aviso visible en la barra de herramientas.
  • “Doing it Wrong” y funcionalidad deprecada en el código de tu sitio.
  • Bloques y sus propiedades dentro del contenido y del Full Site Editing.
  • Rewrite rules coincidentes, query strings y query vars de la petición.
  • Scripts y estilos enqueueados, con sus dependencias, dependientes y alertas de dependencias rotas.
  • Llamadas a la HTTP API, con código de respuesta, componente responsable y tiempo, y alertas de requests fallidas.
  • Verificaciones de capacidades de usuario (capability checks) con su resultado.
  • Información de entorno: PHP, base de datos, WordPress y servidor web.
  • Condicionales: el valor de is_single(), is_home() y todos los demás.
  • Transients actualizados y uso de switch_to_blog() en Multisite.

Además: cuando ocurre un redirect, Query Monitor agrega un header HTTP con el call stack para que traces desde DevTools qué lo disparó; las respuestas de Ajax incluyen datos de debugging en sus headers; y las respuestas de la REST API autenticada incluyen un resumen de performance y errores PHP en headers (una request con _envelope incluye aún más info en la propiedad qm de la respuesta).

Requisitos: WordPress 6.2 o superior (probado hasta 7.0.4) y PHP 7.4 o superior (probado hasta PHP 8.5).

Instalación y el drop-in db.php

Instalás Query Monitor como cualquier plugin:

wp plugin install query-monitor --activate

O desde el admin: Plugins → Añadir nuevo → buscás “Query Monitor” → Instalar → Activar. En nuestra guía de WP-CLI en WordPress Studio vimos cómo instalar y actualizar plugins desde el terminal de Studio (ahí aparece query-monitor en la salida de plugin list); es la vía más rápida cuando tenés varios sitios que mantener.

Lo que pasa al activar: Query Monitor incluye un archivo db.php que se enlaza simbólicamente (symlink) dentro de tu wp-content/. Es un drop-in de WordPress que le permite a Query Monitor mostrar el count de resultados, el stack trace completo y la detección de errores de todas las consultas.

Si el symlink no se puede crear (permisos de wp-content, otro db.php ya existente, o un sitio migrado donde el symlink viejo quedó roto), Query Monitor sigue funcionando pero sin la información extendida de las queries. Para crearlo a mano:

# WP-CLI (recomendado)
wp qm enable

# Linux / macOS
ln -s /path/to/wordpress/wp-content/plugins/query-monitor/wp-content/db.php /path/to/wordpress/wp-content/db.php

# Windows (consola como administrador)
mklink C:\path\to\wordpress\wp-content\db.php C:\path\to\wordpress\wp-content\plugins\query-monitor\wp-content\db.php

Conflictos conocidos: si otro plugin usa un db.php (W3 Total Cache, LudicrousDB, HyperDB, SQLite Database Integration), el archivo no se crea. Es una limitación del core: solo puede vivir un db.php en wp-content/. No hay solución posible más que elegir.

💡 En la 4.0.7, las queries aparecen en el timeline incluso cuando db.php no está en su lugar — pero sin el stack trace extendido.

Visibilidad: quién puede ver la información

Por defecto, el output de Query Monitor solo lo ven:

  • Administradores en instalaciones de sitio único.
  • Super Admins en Multisite.

En WordPress VIP, además, hay que otorgar la capacidad view_query_monitor incluso a los administradores.

Desde el panel de Settings podés:

  • Activar stack traces cliqueables: clickeás un frame del stack y se abre el archivo en tu editor.
  • Setear una cookie de autenticación que te deja ver el output sin estar logueado (o siendo un usuario sin permisos). Útil para debuggear como usuario anónimo — la generás en Settings y la pegás en el navegador.

Mi recomendación para producción: no dejes la cookie de auth activa y no le des la capacidad a roles leídos. El panel de errores PHP de QM es oro para debugging, pero no querés que un atacante autenticado vea stack traces completos.

La barra de herramientas: los 4 números

Logueado como administrador, aparece un ítem nuevo en la barra de herramientas. Los números muestran, en orden:

  1. Tiempo de generación de página (en segundos)
  2. Pico de uso de memoria
  3. Tiempo total de las consultas SQL (en segundos)
  4. Cantidad total de consultas SQL

Simulación del panel de Query Monitor: barra de herramientas con los 4 números y el panel Database Queries agrupado por componente

Figura: representación del menú de Query Monitor en la barra de WordPress — a la vista, los 4 números de la carga (página, memoria, tiempo SQL, cantidad de queries) y el panel de Database Queries con alertas de queries lentas por componente.

Todos los datos son de la carga de página actual. No hay histórico (está planeado para una versión futura).

Clickeá el número superior para abrir el panel Overview, o cualquier otro ítem para ir directo a su panel. Si ves un resaltado rojo o naranja en el menú, hubo un error PHP que investigar.

Los paneles uno por uno

Esta es la lista completa de paneles que puede mostrarte Query Monitor:

PanelQué te muestraPara qué lo usás
OverviewResumen del page load: tiempos, memoria, cache, erroresVista rápida de la salud de la carga
TimelineTodos los eventos en una línea de tiempo horizontalVer dónde se gasta el tiempo real
QueriesCada consulta SQL con stack trace, tipo y componenteEncontrar queries duplicadas, lentas o con errores
Hooks & ActionsAcciones y filtros disparados durante la requestDebug de orden de hooks, qué se dispara y con qué argumentos
PHP ErrorsNotices, warnings y errores con componente y stackInvestigar warnings que rompen comportamiento
Doing it WrongUsos incorrectos de APIs de WordPress (_doing_it_wrong)Detectar código mal escrito
HTTP API CallsRequests HTTP server-side con código de respuesta y tiempoEncontrar llamadas externas ocultas que hacen lento el sitio
Scripts & StylesArchivos enqueueados con dependencias y alertas de roturasOptimizar carga de JS/CSS
TemplateArchivo de template, jerarquía y template partsEntender qué template renderizó la página
BlocksBloques del contenido y del FSE con sus propiedadesDebug del editor de bloques
RequestRewrite rules, query vars y query stringsSaber qué “vio” WordPress en la URL
ConditionalsValor de todas las funciones condicionalesVerificar is_single(), is_front_page(), etc.
EnvironmentPHP, base de datos, WordPress, servidorConfirmar versiones y configuración del host
Capability Checks (off por defecto)Capability checks de usuariosDebug de permisos; requiere QM_ENABLE_CAPS_PANEL
TransientsTransients actualizados en la cargaDetectar escrituras innecesarias
Admin ScreenInfo del contexto del adminDebug de páginas del wp-admin
MultisiteUso de switch_to_blog()Debug en instalaciones de red
REST APIRequests REST con headers de performanceDebug de endpoints autenticados
GuzzleRequests HTTP hechas con GuzzleDebug de librerías que usan Guzzle
Related HooksHooks relacionados con la página actualEncontrar qué hook es responsable de un área
wp_die()Llamadas a wp_die() con su stackSaber qué mató la request
LogsMensajes que vos o plugins registranLogging propio con qm/debug, etc.
TimingsTimers de profiling con qm/start y qm/stopMedir tiempo y memoria de tus funciones
Assertions (nuevo en 3.15)Aserciones que fallaron o pasaronValidar invariantes de tu código

No todos los paneles aparecen siempre: algunos solo se muestran si hubo datos (PHP Errors), otros si hay contexto (Admin Screen, Multisite) y Capability Checks hay que habilitarlo con una constante.

Timeline: la novedad de la versión 4

La versión 4 (abril 2026) trajo un nuevo panel de Timeline que grafica horizontalmente los eventos de la página: consultas SQL, llamadas HTTP API, errores PHP, timings, logs y acciones notables. Podés filtrar por componente y activar/desactivar categorías.

Es el primer lugar donde mirar cuando un sitio es lento: te muestra cuándo ocurrió cada cosa y cuánto tardó, mucho más rápido que leer listas.

La 4.0 cambió además el renderizado de los paneles: de PHP server-side a Preact client-side, con un bundle propio de 100KB y cero dependencias externas (sin jQuery). Beneficios: mucha mejor performance en sitios con miles de queries o errores, y los datos crudos quedan expuestos como JSON en el objeto QueryMonitorData de la consola del navegador — jugá con él si querés remixar datos vos mismo.

💡 Los add-ons de terceros que agregan paneles server-side siguen funcionando igual en la v4. Los paneles client-side de terceros todavía no se pueden registrar: es una mejora futura anunciada.

Database Queries: el corazón del plugin

El panel de Queries es el más usado. Tres vistas agregadas:

  • Queries by Component: tiempo total de queries agrupado por plugin/tema/core. Ordenado por tiempo total — si un plugin hace muchas queries o queries lentas, salta a la vista. Es la forma más rápida de encontrar el plugin que te está arruinando la performance.
  • Queries by Caller: agrupado por función que llamó a la query.
  • Duplicate Queries: queries idénticas ejecutadas más de una vez — el clásico problema N+1 en loops de posts.

Además, cada query individual muestra:

  • El SQL completo
  • El stack trace de quién la llamó (cuando el drop-in db.php está activo)
  • El componente responsable y la función llamadora
  • El tiempo de ejecución y el número de resultados

Una query se marca como lenta si tarda más de 0.05 segundos (configurable con QM_DB_EXPENSIVE). Las alertas visibles te avisan de queries lentas, duplicadas o con errores.

El caso N+1 más común: un loop de posts donde cada uno dispara una query extra (por ejemplo, llamar get_post_meta() o get_the_terms() dentro de foreach). El panel de Queries te muestra las queries duplicadas idénticas y el stack trace te dice exactamente en qué función del tema están. Ahí sabés dónde aplicar pre_get_posts o hacer un solo query con todos los IDs.

Profiling y logging con código

Esto es lo que separa a Query Monitor de cualquier plugin de “optimización”: podés instrumentar tu propio código.

Profiling de tiempo y memoria

// Iniciar el timer 'foo':
do_action( 'qm/start', 'foo' );

// Ejecutar la función que querés medir
my_potentially_slow_function();

// Detener el timer:
do_action( 'qm/stop', 'foo' );

El tiempo y la memoria aproximada entre qm/start y qm/stop aparecen en el panel Timings. Los timers se pueden anidar (con menos precisión en memoria) y usar laps:

do_action( 'qm/start', 'bar' );

foreach ( range( 1, 10 ) as $i ) {
    my_potentially_slow_function( $i );
    do_action( 'qm/lap', 'bar' );
}

do_action( 'qm/stop', 'bar' );

⚠️ Los valores son aproximaciones a nivel PHP — pueden estar desviados por el entorno. Para mediciones de alta precisión usá un profiler de bajo nivel como XHProf.

Logging estilo console.log

En vez de var_dump() y morir, logueás a Query Monitor:

do_action( 'qm/debug', 'This happened!' );

Los niveles siguen PSR-3/syslog: qm/debug, qm/info, qm/notice, qm/warning, qm/error, qm/critical, qm/alert, qm/emergency. Un nivel warning o superior prende la alerta en la barra de herramientas.

Interpolación contextual con llaves:

do_action( 'qm/warning', 'Unexpected value of {foo} encountered', [
    'foo' => $foo,
] );

Podés pasar directo un WP_Error, Exception o Throwable:

if ( is_wp_error( $response ) ) {
    do_action( 'qm/error', $response );
}

Y variables de cualquier tipo se formatean solas. También existe la clase estática QM (compatible PSR-3):

QM::error( 'Everything is broken' );
QM::debug( $var );

⚠️ No loguees valores enormes (arrays de posts enteros, respuestas HTTP crudas). Para eso, debug paso a paso con Xdebug o Ray.

Detener Query Monitor en requests largas

Si un proceso hace muchísimas queries (backup, importación, escaneo de seguridad), detené la recolección:

do_action( 'qm/cease' );

Descartá lo recolectado y saltá el output del resto de la generación de página.

Assertions para tus propias funciones

Desde la 3.15 podés hacer aserciones que loguean un error en el panel Logs cuando fallan:

do_action( 'qm/assert', $value === 5 );
do_action( 'qm/assert', $value === 5, 'Value is 5' );
do_action( 'qm/assert', $value === 5, 'Value is 5', $value );

Por ejemplo, asegurar que procesar cada post no dispara queries nuevas:

foreach ( $posts as $post ) {
    $before = $wpdb->num_queries;
    $this->process_post( $post );
    $after = $wpdb->num_queries;

    // Assert que no hay queries nuevas al procesar cada post:
    do_action( 'qm/assert', $after === $before );
}

Y postcondiciones, por ejemplo que una acción se disparó:

do_action( 'qm/assert', did_action( 'my-action' ) );

También como métodos estáticos: QM::assert( $value === 5 ), etc.

Diferencias con assert() de PHP: las aserciones de QM no terminan la ejecución (soft assertion: el código sigue igual), loguean también los casos que pasan (verificás que se ejecutaron), siempre corren sin importar la configuración de php.ini, y aceptan un valor de debug opcional. Recordá: son para desarrollo, no reemplazan la validación de datos.

Constantes de configuración (wp-config.php)

Estas constantes van en tu wp-config.php para controlar el comportamiento:

ConstanteDefaultQué hace
QM_DB_EXPENSIVE0.05Tiempo (en segundos) a partir del cual una query se considera “lenta” y dispara alerta
QM_DISABLEDfalseDesactiva Query Monitor por completo
QM_DISABLE_ERROR_HANDLERfalseDesactiva el manejo de errores PHP de QM
QM_ENABLE_CAPS_PANELfalseHabilita el panel de Capability Checks
QM_HIDE_CORE_ACTIONSfalseOculta el core de WordPress en el panel de Hooks & Actions
QM_HIDE_SELFtrueOculta a Query Monitor mismo de varios paneles (ponelo en false si querés ver cómo hookea QM)
QM_SHOW_ALL_HOOKSfalseEn Hooks & Actions, muestra todos los hooks con action o filter attachados en vez de solo los que se dispararon
QM_DB_SYMLINKtruePermite que el symlink de wp-content/db.php se cree en la activación

Ejemplo de uso: si estás debuggeando problemas de permisos, activás el panel de capacidades:

define( 'QM_ENABLE_CAPS_PANEL', true );

Workflow: diagnosticar un sitio lento

El orden recomendado por la documentación oficial cuando un sitio anda lento:

1. Timeline. Vista visual de dónde se gasta el tiempo real de la carga. ¿Hay una llamada HTTP que tarda 3 segundos? ¿Un bloque que explota en queries?

2. Queries by Component. El ranking de tiempo de queries por plugin/tema. Un plugin que hace muchas queries o queries lentas se ve al instante.

3. HTTP API Calls. Las llamadas server-side a otros servicios suelen ser causas invisibles de lentitud y ocurren de forma esporádica. Si un plugin llama a una API externa en cada carga, tu TTFB se va al diablo. Un ejemplo real: un plugin de “Orderable” llamaba a un servicio de YouTube en cada page load y agregaba 5 segundos por página.

4. Object Cache. El panel Overview te dice si tenés object cache persistente. Si ves “External object cache not in use”, WordPress usa la cache no persistente: las operaciones se cachean dentro de la misma carga pero no entre cargas. Con Redis o Memcached vía un plugin de object caching, las queries y llamadas HTTP se cachean entre requests y la mejora es enorme.

5. PHP Errors. Los warnings no solo indican código que funciona mal: cada error logueado por el servidor suma tiempo de carga. Un warning que se repite 50 veces en una página es tiempo real perdido.

6. Scripts & Styles. Muchos archivos de JS/CSS no ralentizan el server, pero sí la carga en el navegador del visitante. Si el panel muestra decenas de archivos, considerá minificar y combinar.

💡 Recordá: otros factores (llamadas HTTP, render de bloques) pueden aportar más al tiempo de generación que las queries mismas. Mirá el Timeline antes de hipnotizarte con el SQL.

Query Monitor en producción: qué sí y qué no

¿Dejarlo activo en producción? Sí, con criterio. El impacto de QM en el tiempo de generación es despreciable (hookea pocos lugares, igual que cualquier plugin). En páginas con cientos de queries usa más memoria de la deseada por los stack traces — el autor lo reconoce y lo sigue reduciendo.

Mi configuración recomendada para producción:

  • Activado pero visible solo para administradores (es el default). Así no perdés el acceso al debugging cuando el sitio tiene un problema real — y un problema real rara vez avisa antes.
  • Sin cookie de auth pública y sin dar la capability a roles bajos: los stack traces completos son información sensible para un atacante autenticado.
  • En requests largas (backups, imports, escaneos), usá do_action( 'qm/cease' ) para que no acumule stack traces.

Actualizá siempre: la 3.20.4 (marzo 2026) fue un security release que corrigió un XSS reflejado en el panel Request (GHSA-2xr4-chcf-vmvf). Un plugin de debugging también tiene vulnerabilidades — mantenelo al día como cualquier otro.

Framework, seguridad y add-ons

  • Reporte de bugs de seguridad: vía el Security tab del repo de GitHub (advisory privado, con CVE si corresponde). No se reportan en los foros de wordpress.org.
  • Add-ons: hay una lista en querymonitor.com/help/add-on-plugins. Además, QM soporta de forma transparente los add-ons de Debug Bar: si tenés add-ons de Debug Bar, desactivá Debug Bar y aparecen en el menú de QM.
  • Incluido en hosting enterprise: Altis Cloud y WordPress VIP lo bundlean.
  • Browser extension: existe una extensión de dev tools que muestra el panel fuera de la página — no ocupa espacio en el sitio y se puede redimensionar/desacoplar como cualquier panel de DevTools.
  • Privacidad: QM es privado por defecto: no guarda datos de forma persistente ni contacta a terceros, y su declaración de privacidad y accesibilidad están publicadas.
  • Stack traces cliqueables: activables en Settings, abren el archivo directamente en tu editor.

Qué hacer ahora

  1. Instalá Query Monitor en un entorno de desarrollo o staging: wp plugin install query-monitor --activate, después verificá que el symlink db.php esté en su lugar con wp qm enable.
  2. Andá al panel Queries → Duplicate Queries en tus páginas más pesadas: si ves N+1, el stack trace te dice qué función del tema arreglar.
  3. Revisá el Timeline en una carga real: buscá llamadas HTTP externas y bloques que concentren el tiempo.
  4. Activá el panel de Capability Checks (define( 'QM_ENABLE_CAPS_PANEL', true );) si debuggeás problemas de permisos.
  5. Instrumentá tu código: plantá do_action( 'qm/start', 'mi_funcion' ) alrededor de funciones sospechosas y do_action( 'qm/error', $e ) en tus catches.
  6. En producción: dejalo activo visible solo para administradores, sin cookie de auth, y verificá que esté en la última versión (wp plugin update query-monitor).

Query Monitor es gratuito, no manda datos a nadie y se convirtió en estándar de la industria: está bundlado en WordPress VIP y Altis, y su autor está patrocinado por Automattic. Si desarrollás o mantenés WordPress, es la herramienta que te saca de la categoría “reinicio el sitio a ver si se arregla” y te lleva a “esto es exactamente lo que pasó”.

Fuentes

¿Tu WordPress está caído, hackeado o querés protegerlo antes de que pase? Te ayudo a recuperarlo y blindarlo.

Solicitar diagnóstico