WordPress wp_options Bloat: Find and Fix Autoload Data
If you've already installed a caching plugin, switched to good hosting, and your WordPress site is still sluggish on every request — even the cached ones stutter for a split second before serving — the culprit is probably sitting in a single database table: wp_options. Specifically, rows in it marked autoload = 'yes'.
What autoloaded data actually is
Every WordPress page load runs one query near the very start of execution: SELECT option_name, option_value FROM wp_options WHERE autoload = 'yes'. This isn't optional — core, your theme, and nearly every plugin rely on it to have settings, transients, and cached values ready in memory before anything else runs. WordPress itself caches the result in object cache when one is available, but on a cache miss, or on a host without persistent object caching (which is most shared hosting), that query runs cold on every single request.
The problem isn't that this query exists. It's that plugins keep adding rows to it and never clean up after themselves. A fresh WordPress install has maybe 200-300 autoloaded rows totaling a few hundred KB. We've pulled sites out of production with 40,000+ autoloaded rows and an autoload payload of 15-20MB. That's 15-20MB PHP has to unserialize into memory before it can render a single character of HTML — on every page view.
Symptoms this causes
- TTFB (time to first byte) is high even on pages served from a page cache, because object cache misses still hit this query.
- Site feels randomly slow — fast for a few requests, then a stall — which is the classic pattern of memory pressure from unserializing a huge autoload blob.
wp-adminis noticeably slower than the public site, since admin screens autoload more.- PHP memory limit errors that don't correlate with traffic spikes.
- MySQL slow query log shows the same
SELECT ... FROM wp_options WHERE autoload = 'yes'query repeatedly, often taking 200ms+.
Find out if this is actually your problem
Don't guess — measure it first. If you have SSH access, WP-CLI gives you the total autoload size in one line:
wp db query "SELECT ROUND(SUM(LENGTH(option_value))/1024/1024, 2) AS autoload_mb, COUNT(*) AS row_count FROM wp_options WHERE autoload='yes'"
Anything under 1MB is healthy. 1-3MB is worth watching. Above 3-5MB, you have a real performance problem, and above 10MB you're actively hurting every visitor.
No SSH? Run the same query through phpMyAdmin in cPanel (Databases → phpMyAdmin, select your WordPress database, open the SQL tab, paste the query minus the wp db query wrapper).
To find which options are actually responsible, sort by size:
wp db query "SELECT option_name, LENGTH(option_value) AS bytes FROM wp_options WHERE autoload='yes' ORDER BY bytes DESC LIMIT 25"
In our experience, the top offenders are almost always one of these:
| Option name pattern | Usual cause |
|---|---|
_transient_* and _transient_timeout_* with autoload=yes | Expired transients that were never cleaned up — WordPress should skip these, but old plugin code sometimes saves transients with autoload on by mistake |
woocommerce_*_sessions or similar | WooCommerce session data accumulating for guest carts that were never converted or expired |
wpml_*, elementor_*_data | Page builder and multilingual plugins caching large config blobs per-page |
*_backup_*, duplicator_* | Backup plugins storing scan/progress state in options instead of a dedicated table |
rewrite_rules | Usually fine and small, but occasionally bloats on sites with thousands of custom post types/taxonomies |
How to fix it
1. Clear expired transients first — it's the safest win
wp transient delete --expired
wp transient delete --all
Without WP-CLI, a plugin like WP-Optimize or Advanced Database Cleaner does the same thing through the admin UI. This alone often recovers several MB with zero risk, since transients are meant to be disposable caches.
2. Take the site offline before touching anything else
Before editing rows directly, take a full database backup. In cPanel, go to Backup Wizard → Download a MySQL Database Backup, or run:
mysqldump -u dbuser -p dbname wp_options > wp_options_backup.sql
3. Flip autoload off for large, non-critical options
You generally don't delete options you don't recognize — you change whether they autoload. Most plugin-generated cache blobs don't need to be in memory on every request; they only get read on specific admin screens.
wp option update woocommerce_sessions '' --autoload=no
wp db query "UPDATE wp_options SET autoload='no' WHERE option_name LIKE '%_elementor_data%'"
Do this one option at a time for anything you're not 100% sure about, and check the site after each change. If something breaks, flip it back — this is why the backup from step 2 matters.
4. Remove genuinely orphaned rows from uninstalled plugins
Deactivating a plugin rarely removes its options. If you see option names prefixed with a plugin slug you no longer use, delete them:
wp option delete old_plugin_settings_key
5. Add a persistent object cache if your plan supports it
Redis or Memcached moves this query out of MySQL entirely after the first load, so even a moderately bloated table stops being a per-request cost. On Getwebup VPS and Business hosting plans, Redis is available as an add-on — ask support to enable it and install a plugin like Redis Object Cache to wire it up.
Prevention
- Re-run the autoload size query monthly, or after installing any plugin that handles sessions, backups, or page-builder data.
- Set a WP-Cron job (or a real system cron calling
wp cron event run --due-now) to clear expired transients weekly. - Before installing a new plugin, check its support forum for "slow," "wp_options," or "autoload" — plugins with known bloat issues get called out repeatedly.
- When you remove a plugin for good, use a cleanup tool (WP-Optimize's "Unused options" scan, or manual review) instead of assuming uninstall handled it.
None of this replaces caching, image optimization, or a decent PHP version — those still matter. But if you've done all of that and the site still feels heavy on every load, the database is very often where the weight actually is.
Frequently asked questions
How big should my wp_options autoload size be?
Under 1MB is healthy for most sites. 1-3MB is worth monitoring, especially on shared hosting. Above 3-5MB you'll typically notice slower TTFB, and above 10MB it's actively degrading every page load, cached or not.
Is it safe to just delete unfamiliar wp_options rows?
No — deleting is riskier than disabling autoload. Many options are read rarely but still need to exist. Back up the wp_options table first, then prefer setting autoload to 'no' over deleting, unless you can clearly trace an option to a plugin you've fully removed.
Will a caching plugin fix this on its own?
Page caching (like WP Rocket or LiteSpeed Cache) only helps requests that hit the cache. Object caching (Redis/Memcached) is what actually removes the wp_options query cost, since it caches the autoload payload itself between requests, not just the final HTML.
Why does WooCommerce cause this so often?
WooCommerce stores per-session cart and customer data as options for every guest visitor. On stores with high traffic and low conversion, thousands of abandoned guest sessions can accumulate as autoloaded rows unless session cleanup is running correctly.
Can I automate this cleanup instead of doing it manually every time?
Yes — a weekly cron job running `wp transient delete --expired` handles the safest recurring cleanup. For deeper bloat from removed plugins, a manual quarterly review of the top 25 autoloaded rows (via the query above) catches issues automation would miss.