I got a call about a site that was crawling, especially in the wp-admin dashboard. The client was sure they needed a bigger server, but I have seen this movie before. Nine times out of ten it is not the hardware. It is a rogue plugin or a theme doing something dumb in the database. Sure enough, I fired up Query Monitor and the wp_options table was getting hammered on every page load. This is a classic case of someone misunderstanding the WordPress Options API.
The Options API is how WordPress stores and retrieves all sorts of data, mostly settings for themes and plugins. It is basically a big key-value store sitting in your database. Very handy. But it has one feature that can be either your best friend or your worst enemy: the autoload flag.
The autoload trap in the WordPress Options API
When an option is set to autoload, WordPress loads it into memory on every page. For small bits of data you need everywhere, that is great, because it saves a database query. But the plugin I was debugging had stored a 2MB blob of log data in a single autoloaded option. Every page load was dragging that huge, useless weight along with it.
My first thought was to just switch it off, a quick and dirty fix. You can do that with the third parameter in update_option.
// The quick fix: just disable autoload
update_option( 'the_problem_plugin_option', $huge_data, false );And yes, the site got faster right away. Problem solved? Not quite. A few minutes later the client reported that a frontend widget from that same plugin had stopped working. It turned out the widget needed a tiny piece of that data to run. By turning off autoload I had fixed the performance and broken the feature. A classic rookie mistake. The real fix had to be more careful.
The right way to handle this is to split the option in two. There is a good breakdown of this over at carlalexander.ca that gets into how the data is accessed. Keep the small, essential data in one option that gets autoloaded, and keep the big, clunky stuff in a second option you only load when you actually need it.
// The RIGHT way to fix it
$all_options = get_option( 'the_problem_plugin_option' );
// 1. Create a smaller array with just the essential data
$essential_data = [
'api_key' => $all_options['api_key'],
'widget_title' => $all_options['widget_title'],
];
// 2. Create another array for the non-essential stuff
$non_essential_data = [
'historical_logs' => $all_options['historical_logs'],
// ... other large data
];
// 3. Save the small array with autoload ON
update_option( 'the_problem_plugin_essentials', $essential_data, true );
// 4. Save the big array with autoload OFF
update_option( 'the_problem_plugin_logs', $non_essential_data, false );So what’s the real takeaway?
The lesson here is not really about the autoload flag. It is about being deliberate. Before you save anything to the database, ask yourself a few questions:
- How often do I really need this data?
- Does it need to be available on every single request?
- Could I split it into smaller, more manageable chunks?
Working through those questions is what separates a junior dev from a senior one. You stop causing problems and start building things that stay stable as they grow. It is the difference between a quick patch and a real solution.
This stuff gets complicated fast. If you are tired of debugging someone else’s mess and just want your site to work, drop my team a line. We have probably seen it before.