WordPress, Options, and Auto-loading

There are many different ways WordPress performance can be slowed: not understanding options is one of them.

There are many different ways WordPress performance can be slowed: not understanding options is one of them.

Creating Options

When you’re dealing with data, the options table can be a convenient place to cache information you might need later.  API keys, fragments of HTML, remote server responses.  Storing this data in WordPress’ options table is quick, easy, and useful.

It’s also fraught with problems.

Namely, most of us are using [cci]update_option()[/cci] to create options rather than just update existing data.  This will work, but if the option doesn’t yet exist it’s created with the auto-load parameter set to “yes.”

This is probably not the behavior you’d expect.

Auto-loading

When a request comes in to WordPress, the system will load into memory all options registered with the auto-load parameter set to “yes.”  If you added your option with a call to [cci]update_option()[/cci], then your data is being loaded into memory on every request whether WordPress needs the data or not.

If you use an option to cache a snipped of markup, and it auto-loads on pages not needing that markup, you’re filling up the system memory with unnecessary data.

If you use an option to store your remote API keys, and they auto-load for WordPress requests that aren’t fetching or interacting with the remote API, you’re filling up system memory with unnecessary data.

If you haven’t caught on yet, loading unnecessary data into memory is a bad thing.[ref]If you’re using a caching system like Memcached, auto-loading data unnecessarily can fill up your Memcache buckets quickly and force the system to flush everything more frequently than expected. In some cases, this can essentially negate the benefit of using an external object cache in the first place, so keeping track of where and when your option data loads is hugely important.[/ref]

Not Auto-loading

WordPress’ aptly-named [cci]add_option()[/cci] function allows you to create options without forcing them to autoload.  Unlike [cci]update_option()[/cci], [cci]add_option()[/cci] wll fail if the option already exists – this is one of the main reasons developers update rather than add when they’re working with code.

But there’s a better way.

if ( ! add_option( 'option_name', 'some_value', '', 'no' ) ) {
update_option( 'option_name', 'some_value' );
}

The code above will attempt to add an option first. If WordPress adds it as expected, then everything is stored, nothing is auto-loaded, and we can move merrily along.

If [cci]add_option()[/cci] fails, then we know the option already exists in the database, so we fall back on [cci]update_option[/cci] to update things in the system.  We can wrap this functionality up in our own[ref]I have not prefixed the function name – I fully expect you to add your own prefix should you use this function in your own code.[/ref] utility function:

/**
* Add or update a WordPress option.
* The option will _not_ auto-load.
*
* @param string $name
* @param mixed $value
*/
function add_or_update( $name, $value ) {
$success = add_option( $name, $value, '', 'no' );

if ( ! $success ) {
$success = update_option( $name, $value );
}

return $success;
}

Now you can cache data in options without suffering the performance failings of having everything auto-load!