WordPress Performance Troubleshooting: Finding the Real Bottleneck

Got an email the other day. Subject: “Our site is SUPER slow.” It’s the kind of message every developer gets. Vague, urgent, and you know the client is pulling their hair out. This is where real WordPress performance troubleshooting begins, and it’s rarely about just installing another caching plugin. The client said pages were taking 5-7 seconds to load. A total disaster for any business.

My first instinct, and this is where I wasted a solid hour, was to hunt for a monster query. I figured some junior dev had probably stuck a `get_posts()` call inside a loop—the classic N+1 problem. So I started digging through theme files, running `grep` commands, looking for that obvious, ugly piece of code. I found a few things that weren’t perfect, but nothing that would justify a 7-second page load. It was a dead end. And a humbling one.

Stop Guessing. Start Measuring.

When you’re stuck, go back to basics. The absolute first step is to open your browser’s developer tools and look at the “Network” tab. Forget everything else for a minute. You’re looking for one thing: the Time To First Byte (TTFB). It’s that first long bar in the waterfall. If your server is taking 4-5 seconds just to *start* sending the page, no amount of frontend optimization is going to fix it. That’s a server problem. Period.

In this client’s case, the TTFB was sky-high. That told me the problem wasn’t images, CSS, or JavaScript loading. The bottleneck was PHP or the database. My next move is always the same: install the Query Monitor plugin. If you’re developing WordPress sites without it, you’re flying blind. It’s the single most useful debugging tool out there, as I learned from a great overview on the topic at carlalexander.ca.

Here’s the kicker. It wasn’t a slow database query. Query Monitor has a section for “HTTP API Calls.” And there it was. A social media feed plugin was making an external API call on every single page load. The external service was slow to respond, holding up the entire page render for seconds. No cache. No timeout. A total nightmare.

The Simple Fix for External API Calls

The fix wasn’t to delete the plugin; the client needed it. The fix was to cache the result of that API call. The WordPress Transients API is perfect for this. It lets you store the result in the database for a set amount of time. Instead of hitting the slow service on every page load, we’ll just hit it once every hour.

function get_cached_social_feed() {
    // Check for the cached data first
    $feed_data = get_transient( 'my_social_feed' );

    // If the cache is empty, go get the data
    if ( false === $feed_data ) {
        $response = wp_remote_get( 'https://api.example.com/slow-feed/' );

        if ( is_wp_error( $response ) || 200 !== wp_remote_retrieve_response_code( $response ) ) {
            return false; // Bail if the request failed
        }

        $feed_data = wp_remote_retrieve_body( $response );

        // Cache the result for 1 hour
        set_transient( 'my_social_feed', $feed_data, HOUR_IN_SECONDS );
    }

    return $feed_data;
}

So, What’s the Point?

The point is to have a process. Don’t just guess or blame the host. Nine times out of ten, the bottleneck is right there in the code, often from a third-party plugin making an uncached request. Your process should be:

  • Check the browser Network tab to identify where the delay is (frontend vs. TTFB).
  • If TTFB is high, use Query Monitor to inspect database queries and HTTP API calls on the server.
  • Once you find the slow part, fix it at the source. Often, that means caching data with transients.

Leave a Reply

Your email address will not be published. Required fields are marked *