Autoloaded options could affect performance? Find the rows
WordPress loads these rows into memory on every request, before anything else happens. Once they pass a megabyte, every page on the store pays for it.
The symptom
The whole site is slow, not one page. The admin feels sluggish, the cart is slow even though it is excluded from caching, and time-to-first-byte is poor on pages that should be trivial to serve. Nothing in particular looks wrong, and every fix you try helps a little and not enough.
Since WordPress 6.6, Tools → Site Health says it out loud: Autoloaded options could affect
performance, listed as a critical issue once autoloaded data reaches 800,000 bytes. Plugins can
move that threshold with the site_status_autoloaded_options_size_limit filter.
What it costs
WordPress reads every option row marked autoload = yes into memory on every request, in one
query, before it knows what page it is about to render. That is by design and it is fast when the
data is small.
A WooCommerce store is unusually good at making it not small:
- Plugins that store a whole configuration blob, a licence payload or a cached API response as one autoloaded option.
- Plugins that were removed without uninstalling, leaving their options behind forever.
- Transients that were never given an expiry, or whose cleanup stopped running — which is often the background queue not running showing up somewhere else.
The effect is worst precisely where it hurts most. Cart, checkout and account pages are excluded from page caching by design, so they pay the full cost of that query on every load, for every customer, at the exact moment they are deciding to pay you.
Merchlint reports at 1 MB. For context, a lean store sits in the low hundreds of kilobytes.
Worth knowing: WordPress 6.6 stopped autoloading very large new options by default, so a fresh install is less prone to this. Rows that already existed keep the setting they were given, which is why older stores are the ones that find something here.
How to check it yourself
The total, first:
wp db query "SELECT ROUND(SUM(LENGTH(option_value))/1024/1024, 2) AS mb, COUNT(*) AS rows_
FROM wp_options WHERE autoload IN ('yes','on')"
Then the offenders, which is where the answer actually is:
wp db query "SELECT option_name, ROUND(LENGTH(option_value)/1024, 1) AS kb
FROM wp_options WHERE autoload IN ('yes','on')
ORDER BY LENGTH(option_value) DESC LIMIT 25"
WP-CLI can do the same without SQL:
wp option list --autoload=on --fields=option_name,size_bytes --orderby=size_bytes --order=desc | head -25
Almost always, three or four rows account for most of the total. This is not a problem you solve by trimming everything.
How to fix it
-
Identify the owner of each large row before touching it. The option name usually names its plugin. If the plugin is still installed, the row may be needed — just not on every request.
-
Turn off autoload rather than deleting, where the data is still wanted:
wp option set some_big_option "$(wp option get some_big_option --format=json)" --autoload=noThe option stays; WordPress just stops loading it before every page.
-
Delete leftovers from plugins you no longer have. Those are the safest wins and often the biggest ones. Take a database backup first — this one is genuinely irreversible.
-
Clear expired transients, then fix why they were not being cleared:
wp transient delete --expired -
Re-run the total. If it did not move, you removed the wrong rows.
When it is a false positive
- A single large option a plugin genuinely needs on every request. Rare, but real — some page builders and multilingual plugins do this deliberately. Nothing to fix beyond knowing.
- A store on a host with generous memory and object caching, where a megabyte is loaded from Redis rather than MySQL and costs far less. The number is still worth watching, since it tends to grow.
- A threshold that does not fit your store. It is a setting; a large multi-store installation can raise it rather than live with a check that always complains.
How Merchlint finds it
Merchlint sums the length of every option value marked for autoload and compares the total against the threshold. The finding shows the total, the threshold, the number of rows and the largest individual offenders by name — because a total on its own tells you there is a problem and gives you nowhere to start.
Confidence: F — fact from the database. A sum of stored lengths compared with a number.
This check reads wp_options and nothing else. It changes no rows, deletes no transients and turns
off no autoload flags — the repairs in section four are yours to run, deliberately, with a backup.
That is the whole shape of this plugin: it will tell you exactly which four rows are the problem,
and it will not touch them.
Disagrees with what you see in your store? Write to us — we read every message. contact@merchlint.com