Optimizing WordPress Loading Speed With header.php & .htaccess


Website loading speed matters a lot for every blog/website, especially for people with shared hosting – which is the cheapest available hosting service. Here are a few .htaccess and header.php tricks to increase your website loading speed by 50-70%

Web performance is getting more and more attention from web developers and is one of the hottest topics in web development. First and foremost, loading speed is more than a feature. Speed is the most important feature. If your website or blog is slow, people won't use it.

What speed means to internet giants:

  • For Google – 500 milliseconds of extra load time caused 20% fewer searches
  • For Yahoo – 400 milliseconds of extra load time caused a 5-9% increase in the number of people who clicked "back" before the page even loaded
  • For Amazon – 100 milliseconds of extra load time resulted in a 1% drop in sales

Google, in their ongoing effort to make the web faster, blogged that "we've decided to take site speed into account in our search rankings."

So a slower website will even decrease your search engine ranking too.

Thus loading speed matters a lot. CDN (Content Delivery System) are pretty good for this purpose, but up to a limited extent, and good CDN providers are a little costly.

The good news is that some of the most important speed optimizations can be easily done with simple .htaccess tricks. These can make any website load faster by compressing content and enabling browser caching, and follow the Best Practices for Speeding Up Your Web Site from Yahoo!'s Exceptional Performance team and doesn't cost a cent.

Step 1 Gzip File Compression

Compression reduces response times by reducing the size of the HTTP response.

It's worthwhile to gzip your HTML documents, scripts and stylesheets. In fact, it's worthwhile to compress any text response including XML and JSON.

Image and PDF files should not be gzipped because they are already compressed. Trying to gzip them not only wastes CPU but can potentially increase file sizes.

File compression also saves some amount of your bandwidth.

With .htaccess

  • For Apache Servers

    mod_pagespeed is an Apache module developed by Google and its command directive can be used just like other modules.

    Currently only GoDaddy and DreamHost support the mod_pagespeed module, so if you host with them just copy and paste the following code to your .htaccess file:

    			<IfModule pagespeed_module>
    				ModPagespeed on
    				# using commands,filters etc

    Many of you may be hosting with other hosting providers which do not support the mod_pagespeed module.

    You can use the mod_deflate module (Apache 1.3x used mod_gzip but since Apache 2x mod_deflate is used)

    			<ifModule mod_deflate.c>
    				AddOutputFilterByType DEFLATE text/html text/plain text/xml application/xml application/xhtml+xml text/css text/javascript application/javascript application/x-javascript
  • For Nginx Servers

    If you host on a Nginx webserver copy the following to your .htaccess to enable gzip compression.

    			server {
    				gzip on;
    				gzip_types text/html text/css application/x-javascript text/plain text/xml image/x-icon;

With header.php

If your server doesn't support mod_deflate or mod_gzip you can use this PHP script for gzip compression which works on both Apache and Nginx

Just copy this into your theme's header.php

if ( substr_count( $_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip' ) ) {
	ob_start( "ob_gzhandler" );
else {

Below is the bar graph depicting my website's loading speed without and with gzip compression.

Step 2 Disable ETags

ETags (Entity Tags) are a mechanism that web servers and browsers use to determine if the component in the browser's cache matches the original server. Etags are added to provide a mechanism for validating entities that is more flexible than the date of last modification. An ETag is a string that uniquely identifies a specific version of a component. The limitations of this format is that the string is quoted. The origin server specifies the component's ETag using the ETag response header.

To disable ETags, paste this into your .htaccess file

Header unset ETag
FileETag None

Step 3 Use Browser Caching

With browser caching, we're explicitly instructing browsers to hang onto particular files for a specified period of time. When the file is needed again, the browser is to pull from its local cache instead of requesting it from the server again.

Running a website without caching in place makes as much sense as driving to the store for a glass of water every time you're thirsty. Not only is it impractical and short-sighted, it takes more work!

Browser caching is really useful to get returning users; i.e. it may build loyal permanent visitors to you and also saves a lot of your bandwidth.

A first-time visitor to your page will make several HTTP requests to download all your site's files, but by using the Expires and Cache-Control headers you make those files cacheable. This avoids unnecessary HTTP requests on subsequent page views.

  • For Apache Servers

    Apache enables through the mod_expires and mod_headers modules.

    The mod_expires module controls the setting of the Expires HTTP header and the max-age directive of the Cache-Control HTTP header in server responses. To modify Cache-Control directives other than max-age, you can use the mod_headers module.

    The mod_headers module provides directives to control and modify HTTP request and response headers. Headers can be merged, replaced or removed.

    Add these rules to .htaccess for setting Expires headers:

    			# BEGIN Expire headers
    			<ifModule mod_expires.c>
    				ExpiresActive On
    				ExpiresDefault "access plus 5 seconds"
    				ExpiresByType image/x-icon "access plus 2592000 seconds"
    				ExpiresByType image/jpeg "access plus 2592000 seconds"
    				ExpiresByType image/png "access plus 2592000 seconds"
    				ExpiresByType image/gif "access plus 2592000 seconds"
    				ExpiresByType application/x-shockwave-flash "access plus 2592000 seconds"
    				ExpiresByType text/css "access plus 604800 seconds"
    				ExpiresByType text/javascript "access plus 216000 seconds"
    				ExpiresByType application/javascript "access plus 216000 seconds"
    				ExpiresByType application/x-javascript "access plus 216000 seconds"
    				ExpiresByType text/html "access plus 600 seconds"
    				ExpiresByType application/xhtml+xml "access plus 600 seconds"
    			# END Expire headers

    .htaccess rules for setting up Cache-control header:

    			# BEGIN Cache-Control Headers
    			<ifModule mod_headers.c>
    				<filesMatch "\.(ico|jpe?g|png|gif|swf)$">
    					Header set Cache-Control "public"
    				<filesMatch "\.(css)$">
    					Header set Cache-Control "public"
    				<filesMatch "\.(js)$">
    					Header set Cache-Control "private"
    				<filesMatch "\.(x?html?|php)$">
    					Header set Cache-Control "private, must-revalidate"
    			# END Cache-Control Headers


    1. There is no need to set the max-age directive with the Cache-Control header since it is already set by the mod_expires module.
    2. must-revalidate means that once a response becomes stale it has to be revalidated; it doesn't mean that it has to be checked every time.
  • For NGINX Servers

    The corresponding .htaccess settings in Nginx would look something like this:

    (The example below would tell your visitor's browsers to hang onto HTML, CSS, Javascript, images and favicon for an hour)

    			location ~* \.(jpg|png|gif|jpeg|css|js)$ {
    				expires 1h;

Step 4 Reduce MySQL Database Size

Since WordPress 2.6, WordPress autosave posts while writing which remain even after the post is saved as revision in the MySQL Database. Bigger database also sends the site load time higher. I suggest removing revision feature.

Paste the following to wp-config.php to disable revisions:

define('WP_POST_REVISIONS', false );

If you decide to keep the revision feature on you may also choose to keep the revisions on the database for a fixed number of days, e.g. 10 days.


  1. Adding the expires header does not affect the loading time of the website for a first visit, but you'd be surprised how much the page load is reduced for the next page view / visit from a returning visitor.
  2. Track how your site is doing on: display loading number of queries and time.

    Just paste the following code after the copyright text in your theme's footer.php:

    			<?php echo get_num_queries(); ?> queries in <?php timer_stop(1); ?> seconds.

Do you know or use some other method(s) to optimize the loading time of your blog/website? Don't forget to share them by commenting.

Related Posts
  • Code
    Web Development
    How to Use New Relic With PHP & WordPressRelic retina preview
    Today we will look at how to monitor a PHP application using New Relic. More specifically we will set up a basic WordPress installation and get some performance data about it, in the New Relic dashboards.Read More…
  • Code
    JavaScript & AJAX
    Build a Complete MVC Website With ExpressJSExpressjs adv tut retina preview
    In this article we'll be building a complete website with a front-facing client side, as well as a control panel for managing the site's content. As you may guess, the final working version of the application contains a lot of different files. I wrote this tutorial step by step, following the development process, but I didn't include every single file, as that would make this a very long and boring read. However, the source code is available on GitHub and I strongly recommend that you take a look.Read More…
  • Code
    Creative Coding
    A Look at the WordPress HTTP API: wp_remote_get - the ResponseDiagram http api
    In this series, we've been taking a look at the wp_remote_get WordPress HTTP API function in order to understand how it works, how we can use it, and the optional arguments that it accepts. From here, we're able to write detailed requests; however, that's only half of it - there's also the response. In the second article, we took a look at what a basic response would look like, how to evaluate it, and how to display it on the screen, but we didn't actually talk about the response in detail. If you're looking to write more advanced requests and write more defensive code, then it's important to understand the data that's sent as a response. In this final article, we're going to do exactly that.Read More…
  • Code
    Tools & Tips
    HTTP: The Protocol Every Web Developer Must Know - Part 2Http
    In my previous article, we covered some of HTTP's basics, such as the URL scheme, status codes and request/response headers. With that as our foundation, we will look at the finer aspects of HTTP, like connection handling, authentication and HTTP caching. These topics are fairly extensive, but we'll cover the most important bits.Read More…
  • Code
    HTTP Succinctly: HTTP Web ArchitectureHttp cover
    In the first chapter we talked about resources, but mostly focused on URLs and how to interpret a URL. However, resources are the centerpiece of HTTP. Now that we understand HTTP messages, methods, and connections, we can return to look at resources in a new light. In this chapter we'll talk about the true essence of working with resources when architecting web applications and web services.Read More…
  • Code
    Scaling & Caching
    10 Quick Tips: Optimizing & Speeding Up Your WordPress SiteOptimize
    We recently looked at 11 Quick Tips for Securing Your WordPress Site, which included some easy, but essential tips for the security of your WordPress blog. Today, we'll be looking at how to optimize your site to run as fast as it possibly can. So, without further adieu, here are 10 quick tips for optimizing your WordPress site!Read More…