On every WordPress request, the core executes a single large query against wp_options and pulls every row marked autoload='yes'. Those rows are loaded into $alloptions in PHP memory, deserialized, and made available to any get_option() call without another database round-trip. The design is sound - until one or more options swell to tens of kilobytes and stay flagged for autoload. Then every request pays the price, including short admin-ajax calls that never touch the option in question.
Why this matters
Heavy autoload options hit two metrics directly: TTFB (Time To First Byte) and admin-side INP. A 5MB query from MySQL takes 50-150ms on SSD and 200-500ms on spinning disk; the unserialize step on a deeply nested array adds another 30-100ms. When a site handles 10 requests per second, every one of them (the heartbeat ping, the REST endpoint that lists media, the WooCommerce mini-cart fragment) pays that cost.
In extreme cases where $alloptions reaches 10MB or more, you choke PHP's memory_limit: each worker holds its own copy. A site with 20 PHP-FPM workers and 10MB of autoload burns 200MB of RAM on options alone before any code runs. LCP can climb to 4 seconds on simple pages, well beyond the 2.5-second Core Web Vitals threshold.
How to detect
Run this query in phpMyAdmin or Adminer:
SELECT option_name, ROUND(LENGTH(option_value)/1024, 2) AS kb
FROM wp_options
WHERE autoload = 'yes'
ORDER BY LENGTH(option_value) DESC
LIMIT 20;Anything above 100KB deserves investigation. The total should stay under 1MB on a healthy site. Query Monitor is the friendliest in-browser tool: install it, load any front-end page, and the Database Queries panel reports the autoload weight. In WP-CLI the equivalent is wp option list --autoload=on --format=table --orderby=size.
How to fix
For each heavy option, search the option name on Google and the WordPress.org plugin repo. The key prefix usually reveals the responsible plugin (for example wpseo_taxonomy_meta belongs to Yoast). If the plugin is gone but the option survived, drop it:
DELETE FROM wp_options WHERE option_name = 'OPTION_NAME';If the plugin is still active but the option does not need to be available on every page load (logs, statistics history, transients managed outside the Transient API), flip autoload to no:
UPDATE wp_options SET autoload = 'no' WHERE option_name = 'OPTION_NAME';An option with autoload=no still works through get_option(); it simply triggers its own SELECT when something asks for it. Code that depends on it keeps running.
Common mistakes
Do not touch core-managed options: siteurl, home, blogname, active_plugins, template, stylesheet, permalink_structure. They genuinely need to load on every request, and switching them to no creates an N+1 query storm that slows the site even more. The other classic mistake is editing without a backup. wp_options is critical; one wrong UPDATE bricks the site. Take a snapshot with UpdraftPlus or a quick mysqldump first.
Verifying the fix
Re-run the detection query and confirm the total dropped below 1MB. Watch TTFB in PageSpeed Insights - expect a 100-300ms reduction. Query Monitor should now report under 500KB of autoload weight per page. If Redis Object Cache or Memcached is in use, flush it (wp cache flush or the plugin's Flush button); otherwise the old $alloptions array stays cached and you will not see the improvement until the cache expires.