Skip to content
ThemesIonic — home
Troubleshooting

Autoloaded Options Could Affect Performance: Find the Few Rows That Matter

Site Health raises this critical issue when the autoloaded values in wp_options add up to 800,000 bytes. A couple of rows usually make up most of it, and the newer automatic protection does not apply to them.

5 min read intermediate

"Autoloaded options could affect performance" means the options WordPress loads on every request add up to 800,000 bytes or more. Site Health lists it as a critical issue, with the count and the size, for example "Your site has 1412 autoloaded options (size: 1 MB)". The count rarely matters. Almost always, two or three oversized rows make up most of the total, and they are easy to find.

What the test measures

The check was added in WordPress 6.6 as WP_Site_Health::get_test_autoloaded_options(). It calls wp_load_alloptions(), serializes any array or object values, and adds up the string length of every value. If the total is below the limit, the result reads "Autoloaded options are acceptable".

The limit is 800,000 bytes, filterable:

add_filter( 'site_status_autoloaded_options_size_limit', fn() => 1200000 );

Raising it only moves the line. On every uncached request, those bytes are read from the database, unserialized into PHP memory and kept for the whole request, including admin pages and AJAX calls. Why a WordPress site is slow puts that cost in context.

Which rows count as autoloaded

Since 6.6 the autoload column holds more than yes and no. Four values mean "load on every request": yes, on, auto-on and auto. off, no and auto-off do not. Query all four, largest first:

SELECT option_name, LENGTH(option_value) AS bytes, autoload
FROM wp_options
WHERE autoload IN ('yes', 'on', 'auto-on', 'auto')
ORDER BY bytes DESC
LIMIT 20;

Replace wp_ with your table prefix. Run it with wp db query or in phpMyAdmin.

To see the total the way Site Health sees it, sum the same rows:

SELECT COUNT(*) AS options, SUM(LENGTH(option_value)) AS bytes
FROM wp_options
WHERE autoload IN ('yes', 'on', 'auto-on', 'auto');

The figure will be close to, not identical with, the Site Health number: WordPress measures values after loading them, and the wp_autoload_values_to_autoload filter can remove values from the autoloaded set. Compare the top row with the total. If one row is half the total, you have found the problem, and the remaining hundreds of small options do not matter.

The trap: old rows are not protected

WordPress 6.6 also added automatic protection. When an option is saved without an explicit autoload choice, it gets auto, and if its serialized value is larger than 150,000 bytes it gets auto-off instead (filter: wp_max_autoloaded_option_size). That sounds as if large options can no longer be autoloaded.

They can. The re-evaluation in update_option() only applies to rows whose current value is auto, auto-on or auto-off. A row created years ago with yes keeps yes on every update, however large it grows. So does any row a plugin explicitly saves with autoload on. The rows at the top of your query are usually exactly these: old plugin settings, caches stored as options, logs kept in one array.

A second source is easy to miss: transients. set_transient() with no expiration, when there is no persistent object cache, stores the value as an option with autoload on. A plugin that caches API responses "forever" puts them on every page load.

Identify each large row

Work down the list. The option name's prefix almost always identifies the owner:

Row looks like Likely owner Action
Prefix of a plugin you removed Deleted plugin Delete the row (after a backup)
Prefix of an active plugin, a settings array Active plugin Stop autoloading it
_transient_… with no matching _transient_timeout_… Non-expiring transient Delete it, then find what writes it
A theme's theme_mods_… row Customizer data Usually leave it; check what it stores
Core rows such as cron, rewrite_rules WordPress Leave them; investigate why they are large

A huge cron row deserves its own look: thousands of scheduled events, often duplicates from a plugin that schedules on every request. WordPress Cron explained shows how to list them.

Stop autoloading without deleting

For a row an active plugin needs, change the flag, not the value. WordPress has a function for it:

wp eval 'wp_set_option_autoload( "plugin_big_cache", false );'

It writes off, removes the row from the cached copy of all options, and the plugin keeps working: get_option() falls back to a single query for that row. For several rows at once, wp_set_option_autoload_values() takes an array of names and values.

If you change the column with SQL instead, flush the object cache afterwards with wp cache flush. Otherwise the stored copy of all autoloaded options is served unchanged and Site Health will not move.

For rows belonging to removed plugins, delete them, but take a database backup first; removing a plugin completely covers what else they leave behind.

Common mistakes

  • Raising the size limit with the filter and calling it fixed.
  • Running the query with only autoload = 'yes', which misses on and auto rows on a 6.6+ site.
  • Deleting an active plugin's settings row instead of turning off its autoload, which resets the plugin.
  • Fixing the rows once while the plugin that writes non-expiring transients keeps running. The total climbs back.

Verify

  • The query shows no single autoloaded row above a few tens of kilobytes.
  • Site Health shows "Autoloaded options are acceptable" with the new count and size.
  • The pages that used the changed options still work, and overall database health is unaffected.
  • A week later, the total has not crept back up.

Frequently asked

800,000 bytes of autoloaded option values, which Site Health displays as about 781 KB. The limit can be changed with the site_status_autoloaded_options_size_limit filter. Option names are not counted, only the values.
Yes, functionally. get_option() still returns the value; it just fetches it with its own query when something asks for it. The cost of a mistake is one extra query on pages that use the option, not a broken site.
No. With an object cache, all autoloaded options are stored together as one alloptions entry and fetched on every request, so a large set still costs memory and transfer time. The cache removes the database query, not the size.

Related guides