WP Debug Toolkit 1.2.0 is LIVE. Get $300 discount on the lifetime deal now
Use Discount Code WPDTLTD
Get WP Debug Toolkit

wp dbtk api call --profile calls any WordPress REST endpoint from the terminal and returns execution timing, memory usage, and database query data in structured JSON alongside the response. Three modes control the level of detail: full, queries, and summary. Query capture works in all three modes regardless of whether SAVEQUERIES was configured before the WP-CLI process started, though per-query timing requires SAVEQUERIES to be enabled. 

In This Guide

What Is REST Endpoint Profiling

Browser-based profiling tools require a live browser session, making them unsuitable for headless WordPress environments, CI pipelines, or AI-assisted development workflows where an agent needs to profile an endpoint programmatically. 

wp dbtk api call --profile provides a terminal-native alternative. It dispatches any registered REST endpoint internally and returns machine-readable JSON containing the full response alongside timing, memory, and database query data. 

It does not need any browser, network capture tools, or additional instrumentation. You can profile any endpoint from anywhere you can run WP-CLI.

How It Works

wp dbtk api call dispatches requests through WordPress’s internal REST server using rest_do_request(), eliminating the need for an HTTP round-trip. The call respects all authentication, permissions, and middleware that a live request would encounter.

How Query Data Is Captured

Standard WP-CLI commands produce no database query data because WordPress only logs queries when SAVEQUERIES is true, and WP-CLI does not define it. In full and queries modes, WPDT defines SAVEQUERIES = true immediately before dispatch when it is not already set, enabling WordPress’s native per-query logging with individual timing data for the duration of the call.

When SAVEQUERIES is already defined as false in wp-config.php and cannot be redefined, WPDT registers a query filter hook at PHP_INT_MAX priority. This filter intercepts each SQL query as it executes. 

The fallback captures query count and structure but not per-query timing; the queries object in the output will include a capture_warning field: "Per-query timing unavailable because SAVEQUERIES is disabled for this request." 

For summary mode, WPDT reads $wpdb->num_queries before and after dispatch, which works regardless of SAVEQUERIES state.

The Three Profile Modes

Each mode represents a tradeoff between data richness and output size. 

full returns the complete picture, including timing, memory, detailed query analysis, and PHP errors captured during execution. Use it when you need the comprehensive diagnostic view for a single endpoint. 

queries returns the same data except PHP error capture. Use it when you are diagnosing database load specifically and do not need the error layer. 

summary returns timing, memory, and a single query count. Use it in high-volume automated comparisons where output size and parse speed matter.

What the Output Contains

A successful profiling response is a JSON object with top-level keys status, data, headers, and profile. On error, the shape changes: data and headers are absent, and an error object containing code and message appears at the top level instead. The profile key is present in both cases. It always contains execution_time_ms and memory (with delta_mb and peak_mb). 

In full and queries modes, profile adds a queries object with full analysis including component attribution per query. Mode full additionally adds php_errors. Mode summary adds a minimal queries object containing only total.

Key Guarantees

  • wp dbtk api call dispatches through WordPress’s internal REST server. No external HTTP request occurs, and all endpoint behavior is identical to a real request.
  • In full and queries modes, WPDT defines SAVEQUERIES = true before dispatch when it is not already set, enabling per-query timing data. When SAVEQUERIES is already defined as false, WPDT falls back to a query filter that captures query count and structure without per-query timing; timings_available is false and timing fields are null in the output. Summary mode does not define SAVEQUERIES and uses $wpdb->num_queries directly.
  • Authentication is handled by inheriting WP-CLI’s ambient user context; endpoints requiring authentication will fail with a standard REST error response when no user is set.

Key Concepts

Term / ModeWhat It Covers and When to Use It
--profile=fullReturns execution_time_ms, memory, full queries analysis, and php_errors captured during execution. Use when you need the complete diagnostic picture for a single endpoint.
--profile=queriesReturns execution_time_ms, memory, and full queries analysis without PHP error capture. Use when diagnosing database load specifically.
--profile=summaryReturns execution_time_ms, memory, and a queries object containing only total query count. Use in high-volume automated comparisons where output size matters.
--profile (bare flag)Defaults to full mode. Identical to --profile=full.
execution_time_msTotal dispatch duration in milliseconds, rounded to two decimal places. Covers the full internal request lifecycle.
memory.delta_mbMemory consumed by the request in megabytes. Calculated as usage after dispatch minus usage before.
memory.peak_mbPHP peak memory usage in megabytes for the entire process at the point profiling completes.
queries.by_componentMap of component name to query count. Components are identified as plugin slug, theme:<name>, wordpress-core, or unknown.
queries.slowestArray of up to five queries that exceeded the 50ms slow query threshold, each with sql, time_ms, and component. Present in full and queries modes when per-query timing is available. Empty when no query crossed the threshold, even if many queries ran.
capture_warningPresent in the queries profiling object in full and queries modes when SAVEQUERIES was already defined as false
timings_availableBoolean in the queries object for full and queries modes. true when WPDT successfully defined SAVEQUERIES = true before dispatch and per-query timing data is accurate. false when SAVEQUERIES was already defined as false and WPDT fell back to filter-based capture; slow, total_time_ms, and slowest are null or empty in this case.

Configuration

Full Mode: Timing, Memory, Query Analysis, and PHP Errors

Use --profile=full (or bare --profile) when you need the most complete diagnostic output for a single endpoint.

bash

# Call the posts endpoint with full profiling

# Method and route are positional arguments; --params accepts a JSON object

wp dbtk api call GET /wp/v2/posts --params='{"per_page":2}' --profile=full

# Expected output structure:

# {

#   "status": 200,

#   "data": [ ... ],               // full REST response payload

#   "headers": { ... },            // HTTP response headers

#   "profile": {

#     "execution_time_ms": 45.32,  // total dispatch time in ms

#     "memory": {

#       "delta_mb": 1.24,          // memory consumed by the request

#       "peak_mb": 12.50           // PHP peak memory for this process

#     },

#     "queries": {

#       "timings_available": true, // false when SAVEQUERIES was pre-defined as false

#       "total": 18,               // total queries fired during dispatch

#       "slow": 2,                 // queries exceeding 50ms threshold

#       "duplicates": 0,           // repeated identical queries (after normalization)

#       "by_type": {

#         "SELECT": 16,

#         "UPDATE": 2

#       },

#       "total_time_ms": 38.20,    // cumulative query execution time

#       "by_component": {

#         "wordpress-core": 10,

#         "woocommerce": 8

#       },

#       "slowest": [ // up to five queries that exceeded the 50ms threshold

#         {

#           "sql": "SELECT * FROM wp_posts WHERE ...",

#           "time_ms": 15.40,

#           "component": "woocommerce"

#         }

#       ]

#     },

#     "php_errors": []             // PHP errors captured during dispatch (full mode only)

#   }

# }

✅ What You Should See: A JSON object with a top-level profile key. The queries.total field reflects every database query fired during the request. php_errors is an empty array when no errors occurred.

Use full when you want to see whether PHP errors occur alongside the query load during a single request.

Queries Mode: Query Analysis Without PHP Error Capture

Use --profile=queries when you are diagnosing database performance specifically and do not need the PHP error layer.

bash

# Profile a user endpoint — queries mode omits php_errors from the output

wp dbtk api call GET /wp/v2/users --profile=queries

# Expected output structure:

# {

#   "status": 200,

#   "data": [ ... ],

#   "headers": { ... },

#   "profile": {

#     "execution_time_ms": 32.18,

#     "memory": {

#       "delta_mb": 0.92,

#       "peak_mb": 11.80

#     },

#     "queries": {

#       "timings_available": true,

#       "total": 12,

#       "slow": 0,

#       "duplicates": 1,

#       "by_type": {

#         "SELECT": 12

#       },

#       "total_time_ms": 18.40,

#       "by_component": {

#         "wordpress-core": 12

#       },

#       "slowest": [] // up to five queries that exceeded the 50ms threshold; empty here because slow: 0

#     }

#                                  // no "php_errors" key in this mode

#   }

# }

✅ What You Should See: The same queries analysis as full mode, with no php_errors key present.

Use queries when you are cross-referencing profiling output with the WPDT Database Monitor to isolate which component is generating specific queries.

Summary Mode: Query Count Only

Use --profile=summary when you need a lightweight signal for comparing query counts across many endpoints or test runs.

bash

# Profile a WooCommerce products endpoint — summary mode for high-volume comparisons

wp dbtk api call GET /wc/v3/products --profile=summary

# Expected output structure:

# {

#   "status": 200,

#   "data": [ ... ],

#   "headers": { ... },

#   "profile": {

#     "execution_time_ms": 12.85,

#     "memory": {

#       "delta_mb": 0.48,

#       "peak_mb": 10.22

#     },

#     "queries": {

#       "total": 18               // query count only — no timing or component data

#     }

#   }

# }

✅ What You Should See: A profile object with timing and memory data, and a queries object containing only the total count. This mode produces the smallest output of the three and resolves fastest.

Use summary when you are scripting endpoint comparisons in a CI pipeline and only need to know whether query count changed between runs.

Common Issues and How to Fix Them

wp dbtk api call --profile Reports Zero Queries Even Though the Endpoint Is Known to Query the Database

Likely cause: WP-CLI is not loading the WordPress installation you expect, so the active theme or plugins responsible for the query never execute, or --url points to the wrong site in a multisite install.

Fix: Confirm WP-CLI is connected to the correct installation with wp option get siteurl, then confirm WPDT is active with wp plugin list --status=active. For multisite, pass --url=<subsite-url> to target the correct subsite. If query count is genuinely zero and you are using full or queries mode with no capture_warning in the output, the endpoint itself may not be querying the database for that request, which is expected behavior rather than a profiling failure.

Profiling Output Returns a REST Error Instead of Metrics

Likely cause: The endpoint requires an authenticated user with specific capabilities, and WP-CLI is not running with a user context.

Fix: Add the --user global flag to run the command as an authenticated user:

bash

wp --user=admin dbtk api call GET /wpdebugtoolkit/v1/settings --profile=summary

The profile key still appears in the output when the endpoint returns a 401 or 403. However, the output shape changes on error: data and headers are absent, and an error object containing code and message appears at the top level instead. Timing and memory data in profile are collected regardless of whether the dispatched request succeeds.

Frequently Asked Questions

Does wp dbtk api call --profile actually call the endpoint or simulate it?

It makes a real call through WordPress’s internal REST server using rest_do_request(). No HTTP round-trip occurs, but the call goes through the full WordPress REST dispatch stack: authentication is evaluated, permission callbacks run, and the endpoint handler executes exactly as it would for a live request. On a successful call, the response body appears in the data field alongside the profiling metrics. On error, the output contains status and error (with code and message) in place of data and headers.

Why does WPDT profiling show query data when other WP-CLI commands show nothing?

Standard WP-CLI commands do not collect database query data because WordPress only logs queries when SAVEQUERIES is true, and WP-CLI does not define it. In full and queries modes, WPDT defines SAVEQUERIES = true before dispatching the request, enabling per-query logging with individual timing data. When SAVEQUERIES is already defined as false in wp-config.php, WPDT falls back to a query filter hook, capturing count and structure without per-query timing. Summary mode bypasses SAVEQUERIES entirely and reads $wpdb->num_queries directly.

What is the difference between --profile=queries and --profile=full?

One thing: PHP error capture. Both modes return identical timing, memory, and query analysis data. full additionally registers a PHP error handler during dispatch and reports any errors in the php_errors array. Use queries when you are specifically diagnosing database load and do not need the PHP error layer; use full when you want to see whether PHP warnings or notices occur alongside the query activity for a given endpoint.

Related Documentation

Discovering Registered Routes – Find the route paths you want to profile by scanning all registered endpoints on the site; run discovery first when working in an unfamiliar codebase.

Tracing SQL Queries Per Endpoint – Go deeper on the database layer by cross-referencing profiling output with the Database Monitor to identify which code generates specific queries.

CLI Environment Setup – If your profiling output returns unexpected results or authentication failures, verify your WP-CLI environment is connected to the correct WordPress installation before investigating further.

On this page
Try WP Debug Toolkit
The best error log viewer with amazing developer tools to help you troubleshoot your WordPress site securely and efficiently. Something something more.