
Every time WordPress boots, before it renders a single pixel, it runs one database query to pull every option marked autoload = yes from the wp_options table into memory. In a fresh install that payload is tiny. On a site that has installed and uninstalled a dozen plugins over the years, that payload can balloon to several megabytes. Every request pays that tax, cached or not, because object cache priming happens at bootstrap. That is the silent killer: bloated autoloaded options hiding in plain sight.
Why Autoloaded Options Hurt So Much
The autoload mechanism exists for a good reason. WordPress needs fast access to core settings like siteurl, blogname, and active plugin lists without making dozens of individual queries. The design assumption is that autoloaded data is small and frequently needed. The problem is that plugins often mark their options for autoloading as a convenience, even when those options are only needed on specific admin screens or run once a day.
When autoloaded data grows large, several things happen:
- The bootstrap query transfers more data from the database server to PHP on every request.
- PHP has to deserialize (using
maybe_unserialize) every value in that result set, even values your current request will never touch. - If you are using object caching with Redis, that entire payload is stored and retrieved from the cache on each request, consuming memory and adding latency proportional to size.
- On high-traffic sites the database server sees repeated large reads that compete with write queries, which can raise overall query times.
The Core Web Vitals metric most directly affected is LCP (target: 2.5 seconds or under), because time-to-first-byte feeds directly into when the browser can start rendering. A bloated autoload query adds real milliseconds to every request, and milliseconds compound.
Step One: Measure the Damage
Before you change anything, get a number. Connect to your database and run this query:
SELECT
COUNT(*) AS total_options,
SUM(LENGTH(option_value)) AS total_bytes,
ROUND(SUM(LENGTH(option_value)) / 1024 / 1024, 2) AS total_mb
FROM wp_options
WHERE autoload = 'yes';Under 1 MB is generally fine. Between 1 MB and 3 MB is worth investigating. Above 3 MB you almost certainly have a problem that is affecting real users.
Next, find the biggest individual offenders:
SELECT
option_name,
LENGTH(option_value) AS size_bytes,
ROUND(LENGTH(option_value) / 1024, 1) AS size_kb,
autoload
FROM wp_options
WHERE autoload = 'yes'
ORDER BY size_bytes DESC
LIMIT 30;This gives you a ranked list of the thirty largest autoloaded rows. Print it out or copy it somewhere. You will refer back to it throughout the cleanup.
If you prefer wp-cli, the wp option list command can help, though it does not natively sort by size. For a quick scan of specific options you suspect, use:
wp option get option_name_hereAnd to check the autoload status of any option:
wp option pluck option_name_here --format=tableStep Two: Identify What Each Option Belongs To
Most plugin options follow a naming convention that makes attribution easy. A row named my_plugin_settings or wpseo_options tells you exactly which plugin owns it. For rows with less obvious names, a quick search through the plugin’s source code for add_option or update_option with that key will confirm ownership.
Sort your list into three buckets:
- Active plugin options you recognize: These may be reducible but should not be deleted.
- Options from plugins no longer installed: These are safe cleanup targets after verification.
- Transients stored as options: Rows with names starting
_transient_or_site_transient_that are not expired. These should not be autoloaded at all.
Step Three: Clean Up Orphaned Options Safely
Always take a full database backup before making any changes. On the command line:
wp db export backup-before-autoload-cleanup.sqlFor options that belong to plugins no longer installed, you can delete them. Use wp-cli for safety rather than raw SQL deletes:
wp option delete abandoned_plugin_option_nameIf you have a batch of clearly orphaned rows with a shared prefix, you can delete them in SQL, but be conservative. Delete one, verify the site still works, then continue. Never mass-delete rows you have not individually confirmed are orphaned.
For expired transients stored in wp_options (this happens when no persistent object cache is present), wp-cli can clean them up cleanly:
wp transient delete --expired --allIf you are running Redis as a persistent object cache, transients are stored there instead of in the database, which removes this problem entirely. That is worth knowing when you are evaluating your stack.
Step Four: Change Autoload Status Without Deleting
For large options from active plugins that do not need to load on every request, you can set autoload to no without touching the value. The option stays available for the plugin to retrieve with get_option(). It just will not be pre-loaded at bootstrap.
UPDATE wp_options
SET autoload = 'no'
WHERE option_name = 'some_large_option_name';After making this change, test the plugin thoroughly. Most options that plugins retrieve on every page load will have been set to autoload for a reason. Options retrieved only on settings pages, during cron jobs, or for one-time setup are the safe targets here. If a plugin breaks after you flip an option, revert it:
UPDATE wp_options
SET autoload = 'yes'
WHERE option_name = 'some_large_option_name';There is no wp-cli command to change autoload status directly as of the WordPress 6.x era, so SQL is the right tool for this specific task. Wrap your change in a transaction if your database client supports it, so you can roll back instantly if needed:
START TRANSACTION;
UPDATE wp_options SET autoload = 'no' WHERE option_name = 'target_option';
-- test the site here
COMMIT; -- or ROLLBACK;Step Five: Address Root Causes
Cleanup is valuable, but the problem will return if you do not address the source. A few habits help:
- Audit plugins before installing them. Check whether a plugin has a known history of bloating
wp_options. Reviews and support threads often surface this. - Clean up after uninstalling plugins. Some plugins remove their data on deletion; many do not. Run the autoload size query after any plugin removal and clean up anything left behind.
- Use a persistent object cache. Redis or Memcached means WordPress only has to deserialize the autoload payload once per cache warm cycle rather than on every request. This does not shrink the payload, but it dramatically reduces the per-request cost of a moderately large one.
- Monitor regularly. Add the total autoload size query to a periodic checklist, perhaps monthly. Catching growth early is far easier than diagnosing a slow site months later.
A Note on Automated Tools
Several database optimization plugins offer to clean autoloaded options automatically. Be cautious with these. Any tool that bulk-deletes or bulk-flips autoload flags without asking you to review the specific rows is a risk. Use them only if they show you exactly what they intend to change and let you confirm each category. The manual SQL approach described above takes longer but gives you complete control and a clear audit trail.
Measure Again After Cleanup
Run your size query again after cleanup and compare to your baseline. Then measure real-world performance with PageSpeed Insights, keeping in mind that lab data and field data can differ. A significant reduction in autoloaded data typically shows up as a small but consistent improvement in time to first byte, which flows through to LCP scores. On a high-traffic site, even a 50-millisecond improvement per request is meaningful at scale.
Autoloaded options are one of the less glamorous WordPress performance topics, but they are one of the most reliably fixable. The work is methodical rather than complex: measure, identify, verify, clean up, and monitor. Do it once properly and your site carries less dead weight on every single request from that point forward.