DiggingIntoWordPress

by Chris Coyier & Jeff Starr

Optimize WordPress Performance with the wp-config.php File

Posted by on

As you may recall, there are a ton of configuration tricks available for the WordPress wp-config.php file. So many in fact, that I think many people may have missed some of the choice definitions aimed at optimizing WordPress performance. In this post, we’ll explore the best ways to improve your site’s performance with WordPress’ wp-config.php file.

Hardcode your Blog Address and Site Address

Every time your site references your Blog Address or Site Address via WordPress template tags, a query must be made to your database. Update: apparently, the database is only queried for these values for each page load, not for every use of a template tag (thanks to Nathan Rice for the clarification). This happens more often than you may realize, as there are a number of template tags and parameters that access this information:

  • <?php get_bloginfo('url'); ?> — Returns the URL of your site
  • <?php get_bloginfo('wpurl'); ?> — Returns the URL of your blog
  • <?php bloginfo('url'); ?> — Displays the URL of your site
  • <?php bloginfo('home'); ?> — Displays the URL of your blog

These tags display or return the associated information about your blog based on the information supplied in the General Settings panel in the WordPress Admin (Settings > General). Once entered in the Admin, your Blog Address and Site Address information is stored in the WordPress database and must be queried for every instance of each of the above template tags (and probably others as well). This may not seem like much, but the net effect on performance can be significant.

Fortunately, WordPress provides a way to eliminate these unnecessary database queries by enabling us to hardcode the values directly into the PHP construct. By defining the WP_HOME and WP_SITEURL constants in your site’s wp-config.php file, you can boost performance by reducing the number of queries made to your WordPress database. The following two definitions were introduced in WordPress version 2.2 and override the database values without actually changing them (note that you should not include a trailing slash at the end of either URL):

define('WP_HOME', 'http://digwp.com'); // blog url
define('WP_SITEURL', 'http://digwp.com'); // site url

Note that these settings should match those specified in your WordPress Admin. Also, once these values are defined in the configuration file, they will be “greyed out” in the Admin General Settings panel. Removal of the definitions will restore your ability to edit them via the Admin panel.

Hardcode your Template Path and Stylesheet Path

In a similar vein, we may further optimize performance by eliminating database queries for your site’s Template Path and Stylesheet Path. These two variables are defined based on the intrinsic structure of the WordPress installation as well as the name of the currently active theme. Many WordPress themes employ the following template tags to determine the values of these two variables:

  • <?php get_bloginfo('stylesheet_directory'); ?> — Returns the URL of the stylesheet directory of the active theme
  • <?php get_bloginfo('template_directory'); ?> — Returns the URL of the active theme’s directory
  • <?php bloginfo('stylesheet_directory'); ?> — Displays the URL of the stylesheet directory of the active theme
  • <?php bloginfo('template_directory'); ?> — Displays the URL of the active theme’s directory
  • <?php get_stylesheet_directory(); ?> — Returns the stylesheet directory path for the current theme
  • <?php get_template_directory() ?> — Returns the absolute path for the template directory of the current theme

These tags function by assuming a standard directory structure for the WordPress installation (i.e., /wp-content/themes/) and then query the database for the value of the current active theme.

As with the predefined constants for Blog Address and Site Address (see previous section), you can also boost performance by eliminating database queries for your site’s Template Path and Stylesheet Path. The following two definitions were introduced in WordPress version 2.2 and override the database values without actually changing them (note that you should not include a trailing slash at the end of either URL):

define('TEMPLATEPATH', '/absolute/path/to/wp-content/themes/H5');
define('STYLESHEETPATH', '/absolute/path/to/wp-content/themes/H5');

Note that hardcoding these values will disable your ability to switch themes successfully via the WordPress Admin (Appearance > Themes). To do so, simply remove these two definitions, make the switch, and then edit them with the name of the new theme.

Define your four Salt Values

In my article, WordPress Configuration Tricks, I discuss the four security keys that were introduced in WordPress version 2.7. These four keys work silently in the background and protect your site by enhancing cookie encryption. The values for these four keys should be as random and complicated as possible, and are easily and automatically generated at the WordPress.org secret-key service. These predefined keys are placed into your wp-config.php file and may be changed at any time (thereby nullifying your visitors’ old cookies):

define('AUTH_KEY',        '#Sl2}YZFq~~.g=3HT 4+_;l7;#N~e]5._J!u*Y=qvFNhi(E{B9p% }+>rnh8t~Bl');
define('SECURE_AUTH_KEY', 'G/Huwa6Ri6zkkEqz (~*J$O8M72pe>+YrdW|+N_s2*qD%rM,;jF1%c3M!vQ>2`{i');
define('LOGGED_IN_KEY',   'r/N1ssKv7Vxnd2Oj!O3oP+/-[}eSboXBt=(%T`.N7aA%}I%|-):[&@D`r>:Rk_R#');
define('NONCE_KEY',       '~1 -@]b]LMEPzbv#)d1Cz(.7_KHVyP@UG[J&31_r5aC0WAWxpvGF;a^-@YnWt7x@');

Used in conjunction with these four definitions are four corresponding “salt” values. Ideally, these four salt values are as complex and random as the their four encryption-key counterparts. If the salt is not defined elsewhere, WordPress will query the database to generate their values. These generated values are then stored in the WordPress database and must be queried for every use of the encryption keys. Obviously, eliminating these database queries will serve us well in boosting the performance of our WordPress-powered sites. Thanks to the heads up from Peter van der Does, we now know that these four salt constants also may be defined in the wp-config.php file. Here is an example:

define('AUTH_SALT',        '>#m3m?hTy0Lg<oB=ko7Z`8Z&(1gs=FhPug^NniIVpkdo+& c+$]B),H9*7ZMfDGT');
define('SECURE_AUTH_SALT', 'f~N>{|CYc5uuED{^f7)+hEbnh(E,<* 3:7DFcc$)SJS|=Tw^};@ti$714f:-zxjC');
define('LOGGED_IN_SALT',   ':-HRrr}<zW=QwH8F!aUa#|q-xe(pjFK$wt!8G69ttHp4hNfxs[+u-mdxF=3ll{5e');
define('NONCE_SALT',       'F)H4}[Xh?F={lMW8F|gVH~iI!8$0*?X!7IZfr`0Q2-P1EL?:E[0hE>>(+!tTZ/H$');

Exactly how do these salt values interact with their corresponding security keys? As Peter explains in his comment:

The NONCE_KEY, for example is used by the functions wp_nonce_field and check_admin_referer. The strings passed on by these functions are used to create a unique hash. The function used is to create this hash is hash_hmac and the key for this function is the NONCE_KEY + NONCE_SALT.

The bottom line here is that, by including these four salt definitions alongside your four security keys, you can improve site performance by eliminating extraneous database queries. You can even use the same secret-key service to generate the random data (just remember to only copy the salt values and not the entire block of code). And, as with the security-key definitions, the salt values may be changed at any time.

25 Responses

  1. Had no idea you could hard code wp_home, sitepath, stylesheet, etc….. that is so much better than searching and replacing the individual php calls in the theme…. soooo much better. Thanks for the heads up!

  2. Ryan Rampersad July 8, 2009

    I love the secret key service; it can be used for more than just protecting wordpress hashes, it can be used any place you need a secure salt. Just remember to go to the https service so nobody listens to your key/salt traffic.
    https://api.wordpress.org/secret-key/1.1/

  3. Darfuria July 8, 2009

    Really fantastic article. It’d be great to see some performance differences on a high traffic website.

  4. Please, the Constants TEMPLATEPATH and STYLESHEETPATH will have the absolut path, example /www/htdocs/w0012345/wp-content/themes/classic

    You can analyse the constants example with the plugin Debug Options.
    Best regards

    • Good catch, Frank — the post now shows absolute paths in the examples. Cheers.

    • I’m still struggling to get this to work. Can you give an example of a path with a cpanel host, and a path with a xampp test installation?

  5. Ben Forchhammer July 8, 2009

    Sorry, but I don’t think any of the suggested speed improvements in this article actually do improve the speed on a WordPress blog:

    Hardcoding blog address, site address, stylesheet and template path in constants does not prevent database queries.
    a) these calls internally use the get_option() which is cached and never loads the same variable twice.
    b) defining the constant overrides the option value only after the database call / loading which means you don’t save anything by defining them (but rather loose the flexibility of simply changing the values on the fly / in the admin backend).

    2) As far as I know the SALT values are only used when respective KEY values are not defined or invalid (see function wp_salt() in pluggable.php). Only if both constants (key and salt) are not set then a get_option() call is executed (which again is already cached so probably will not slow you down all that much).

    • Ben Forchhammer July 8, 2009

      Ups, I take that 2nd bit back; SALT and KEY do get used together and you do have a get_option() call each time if the SALT values are not defined. (which means this potentially does increase the performance a little bit).

      I still don’t think that avoiding more calls to the get_option() function will increase the performance much. And if it does then the speed improvement would not come from a reduced number of database calls me thinks. (In that case some performance testing and numbers would be nice to see).

      • Ben,
        You’re absolutely right about that. Nearly all the built in WP options are loaded with autoload ON, meaning the get pulled from the DB and cached on each pageload, regardless of whether or not you use them. They are likely pulled using a single SQL query, making their overhead very cheap.

        Use them, or don’t use them … it won’t speed up your system one bit, other than the nominal time it takes for the function to execute. It does NOT query the database ever time you use them, and therefore does NOT affect performance in any significant way.

      • Thanks for the clarification — I have updated the article with the database-query information. Much appreciated.

      • To be more exact, the options are loaded in wp_load_alloptions() (404 link removed 2014/05/04), which is the very first function to do a query on page load since 2.7, when this patch went in.

  6. This (relatively) new WP related site is awesome. Keep it up! I love the fact that the containing block for source code expands horizontally on mouse-over. Nicely done.

  7. Smooth Criminal July 8, 2009

    what about WP_CONTENT_DIR ? This could be less lookups for images and other media

  8. Ian Rountree July 8, 2009

    I imagine this is more useful for finability on SEO than actual load speed, but I do have to wonder how well this technique plays with updating to new versions of WP. Are we adding another step to the upgrade pocess by doing this – ie, reseting our internal edits when WP is updated?

    • No, the wp-config.php file should not be overwritten during the upgrade process — so no extra steps involved.

  9. Coheed July 8, 2009

    “…information is stored in the WordPress database and must be queried for every instance of each of the above template tags…”

    Is there any proof that this is true? Is there any proof that what this post says to do actually improves site performance in a noticeable way?

    It makes no sense at all that WP would query the database every single time one of these functions are called. WP may or may not be coded efficiently, but doing it this way would be flat-out retarded.

    I’m guessing what happens is that WP builds up some object once when a page is viewed with all of these variables and these “tags” simply return their values. In other words, I’m willing to bet the code for bloginfo('url') looks something like…

    function bloginfo($thing) {
         echo WP_ObjectThing['bloginfo'][$thing];
    }

    …rather than…

    function bloginfo($thing) {
         $query = 'SELECT '. $thing .' FROM wp_options [...]';
         # etc etc etc
         echo $thingGottenFromDb;
    }

    If that’s true, and I’m guessing it is, then that object will still be built regardless of what you put in wp-config.php, meaning the database will still be queried, and you’ll have saved pretty much nothing.

    All you’ll have done is sacrifice a little CPU time to call a function for extra memory usage via defining constants.

    Can someone prove me right or wrong? Either would be great.

    • Ben Forchhammer July 8, 2009

      Most values in get_bloginfo / bloginfo() are actually stored as options so the internal function get_option() is used to retrieve them.

      get_option() is cached, each value is only retrieve from the database maximum one time and most options are autoloaded in one big lump when the page is initialised any way.

      I agree that all you save is a little CPU time (if at all) but definitely no database calls. See my comment further up and Nathan Rice’s reply.

  10. i added the key/salt values to my wp_config, but then i could no longer login to my wp admin site. i got a page saying i didn’t have enough permissions. what am i missing??

    love the site btw!

    • Smooth Criminal July 8, 2009

      try cleaning your site domain cookies in browser

  11. Free wordpress themes July 8, 2009

    wow! those are great tips. I do not know that we can hardocode all these urls in wp-config. I was manually replacing the same in wp theme.

    Thanks a lot for your tips. Keep up the great work :)

  12. Excellent tips, I think it will help me getting more traffic thanks

  13. Hal Burgiss September 14, 2009

    I have often wondered if the repetitive calls to bloginfo() used by many themes was significanlty less efficient than accessing the same information via variables or contants. Good programming practices would tell you function calls are generally more expensive than variable retrievals. So what I did was a loop with 1000 iterations and compared the two approaches. The loop took almost exactly twice as long using the function call as a reference to a constant. In real world usage though, I question whether the improvement is measurable.

  14. Sergi Avila June 14, 2012

    I have a problem with:

    define('TEMPLATEPATH', $_SERVER['DOCUMENT_ROOT'].'/themes/fp');
    define('STYLESHEETPATH', $_SERVER['DOCUMENT_ROOT'].'/themes/fp');

    Don’t let me edit the theme because it says that there is no directory of themes but the page works.

Comments are closed. Contact us with any critical information. Thank you!

Code is poetry