My WordPress Autoload Options Hit 1.9 MB and One Row Was Two Thirds of It

The Short Version

  • One row was 65 percent of it. A single expired transient held 1,284 KB of a 1,966 KB payload.
  • I turned nine orphans off instead of deleting them. All nine still hold their full values 25 days later.
  • Site Health reported the old number after the fix. A stale copy was still coming out of the object cache.
  • The query in every tutorial undercounts. On my site it says 325 KB. The real figure is 519 KB.
  • It did not make the site faster. Autoload fell 74 percent and time to first byte did not move.

Site Health on sitezinc.com had one critical issue sitting on it, and it was my own doing. My WordPress autoload options came to 1,966 KB across 1,487 rows. WordPress flags that total at 800 KB. I was at two and a half times the line.

That was August 27. It's my own site, so nothing here needs anonymizing and I can name every value.

My going-in theory was the boring one. Years of plugins installed and removed, a site that's been around a while, death by a thousand cuts. Spread across 1,487 rows, that is what it looks like from the outside.

I was wrong. One row was 1,284 KB. Sixty-five percent of the entire payload sat in a single option, and that option was a transient, which is to say it was cache. Data WordPress generates for itself and is supposed to throw away. Here is what I found, what I cut, what I deliberately did not cut, and the part that still bothers me, which is that none of it made the site any faster.

One Row Was 1,284 KB and It Was Cache

The row was _transient_dirsize_cache. WordPress uses it to remember how big your directories are so it doesn't have to walk the filesystem every time something asks. It's disposable by design. It has an expiry on it. And on my site it was autoloaded, which meant every uncached request was dragging 1.2 MB of directory size math out of the database whether anything on the page wanted it or not.

Deleting it was safe, and it is the one row here I did delete. WordPress rebuilds it the next time it needs it.

Note that deleting that single row would have been enough on its own. 1,965.7 KB minus 1,284 KB is 681.7 KB, which is already under the 800 KB line. The critical issue would have cleared and I could have closed the tab. I kept going, and whether that was the right call is a question I come back to at the end.

Why I Turned Nine Rows Off Instead of Deleting Them

The rest of the payload was orphans. Nine options left behind by plugins that were uninstalled long ago: five from an SEO plugin I replaced, two from a course plugin, one from an analytics plugin, and one from a site management plugin. Ninety KB between them, still loading on every request for code that isn't on the server anymore.

The obvious move is DELETE. I didn't take it, and this is the part of the story I'd argue about.

Setting autoload to off leaves the row exactly where it is. The data survives, the option still reads fine when something asks for it by name, and it just stops riding along on every page load. If I ever reinstall one of those plugins, one value flips back and all its settings are still there. A delete is a one-way door. The plugin comes back to factory defaults and whatever was configured is gone, and nobody remembers what it was.

I checked all nine afterward to confirm they still held their full values, not truncated stubs. They did. I checked again this morning, 25 days later, and they still do. The biggest of them is 44.9 KB of SEO configuration that cost me nothing to keep.

The Query in Every Tutorial Undercounts by 37 Percent

This is the part I'd want you to take away even if you skip everything else, because it means most people auditing their WordPress autoload options are reading the wrong number.

WordPress 6.6 changed how the autoload column is written. According to the Make WordPress Core dev note on the Options API, new writes land as on, off, auto, auto-on or auto-off instead of the old yes and no. There's no upgrade routine, so old rows keep the old values and the two sets live side by side forever.

My wp_options table has all five in it right now: 984 rows marked yes, 379 marked auto, 251 marked off, 186 marked no, and 106 marked on.

That matters because the query in every autoload cleanup article is WHERE autoload = 'yes'. Run that on my site today and it reports 984 rows and 325.0 KB. The real answer is 1,469 rows and 519.3 KB. The tutorial query is 194 KB light, which is 37 percent of the total. You'd read 325 KB, decide you were comfortably fine, and close the tab.

Click to see the SQL code: counting autoload correctly on WordPress 6.6 and later (11 lines)
SELECT COUNT(*) AS autoloaded_rows,
       ROUND(SUM(LENGTH(option_value))/1024, 1) AS kb
FROM   wp_options
WHERE  autoload IN ('yes', 'on', 'auto', 'auto-on');

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

Note that auto-off is not on that list, and leaving it out is correct. That value means WordPress looked at the size on write and decided on its own the row was too fat to autoload. Anything over 150,000 bytes gets that treatment automatically now. Those rows aren't loading, so they don't belong in the count.

Site Health Kept Reporting the Old Number

Here is the one that would have sent me in circles. The writes went through, the database was correct, and Site Health carried right on showing the old figure. Nothing I had just done appeared to have worked.

A stale copy of the options blob was still being served out of the object cache on this site. The database was already right and the thing reading it wasn't. Purging that cache was part of the fix, not a cosmetic step afterward, and anyone working from a generic cleanup tutorial would have concluded the cleanup had failed and gone hunting for more rows to delete. That's how a tidy job turns into a mess.

What the Cleanup Did Not Fix

The WordPress autoload options total went from 1,965.7 KB to 591.7 KB. A 70 percent cut on the day, and 74 percent against where it sits now. Time to first byte did not move.

I measured the homepage again this morning with cache-busting query strings so nothing could serve me a saved copy. 2.90 seconds, 2.61 seconds, 2.58 seconds. That is the same band it was in right after the cleanup. Three weeks of it sitting clean bought nothing measurable at the front door.

So here's the honest read. Autoload was a real problem and it was worth fixing, and it was not this site's performance problem. Time to first byte at 2.6 seconds is, and it's still open. I don't yet know what's spending that time. I'd rather say that plainly than dress the autoload number up as a speed win, which is what most write-ups of this kind of work quietly do. It's the same trap as rightsizing every image on a site and expecting the page to feel different.

There are two live tradeoffs I accepted. The nine options are off, so if one of those plugins ever comes back, WordPress pays an extra query per page for each option it genuinely needs. I'd take that every time over 90 KB on every request for plugins that aren't installed. And the transient will regrow, because that's what cache does. It's empty today. If it ever climbs back toward 1.2 MB, something on this site is scanning a very large directory, and that's a different problem I'd have to go find.

Where the Numbers Sit 25 Days Later

I re-ran the measurement this morning rather than repeating August's figures as if they were current. The WordPress autoload options now total 1,469 rows and 519.3 KB. It has drifted down another 72 KB since the cleanup on ordinary churn, which is what a site that isn't accumulating junk looks like.

There is no _transient_dirsize_cache row at all. In fact there are zero autoloaded transients on the whole site, which is the state you want and almost nobody checks for.

One more thing, and it's the check I'd recommend to anybody doing this work. The arithmetic reconciles. 1,965.7 KB minus the 1,284 KB transient is 681.7 KB. Minus the 90.0 KB of orphans is 591.7 KB, which is exactly what the table finished at. To the tenth of a KB. That is how I know nothing else moved on the site that afternoon, and it's a much better verification than reloading Site Health and squinting at it.

Would I Do It This Way Again

Mostly yes, with one change. Next time I audit WordPress autoload options I'll sort the table by size first and stop after the biggest row. Deleting the transient alone put me under the threshold. The nine orphans were 90 KB out of 1,966, which is 4.6 percent, for nine writes and nine verifications and a cache purge. Fine to do on my own site on a Wednesday. I would not put that on a client invoice and call it performance work.

The part I'd keep without hesitating is autoload off over delete. It costs nothing, it's reversible with one value, and I've never once regretted still having the data.

And the part I got wrong was the theory. I went in expecting a thousand small cuts and found one row holding two thirds of the weight. That has happened often enough now that I check the top of the list before I believe any story about slow accumulation, on my own sites and on other people's. It's the same lesson a fatal error that ran on this site for 19 days taught me from the other direction. Disproving your own theory is the useful part of the job. The finding is just what's left over.

Sources

0 Comments

Submit a Comment

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Post Search

Follow Us

Feel free to follow us on social media for the latest news and more inspiration.

Related Content