Optimal Apache compression and expire settings

Below are compression and expiration settings for Apache that I’ve found optimal for StepMania.  You can paste them into your .htaccess file.

  • Don’t mess with PHP’s ob_gzhandler.  The settings below enable compression at the Apache module level, are the cleanest way to handle compression of non-PHP types, and are better performing to boot.
  • If your PHP application has a option for compression (it’ll be using ob_gzhander), turn that off in favor of these settings.
  • Web-Sniffer is useful for testing whether your compression and cache-control settings are taking effect. It’s also useful for troubleshooting HTTP error responses that Firefox and Chrome hide with pretty error pages.
<IfModule mod_deflate.c>
AddOutputFilterByType DEFLATE text/plain
AddOutputFilterByType DEFLATE text/html
AddOutputFilterByType DEFLATE text/xml
AddOutputFilterByType DEFLATE text/css
AddOutputFilterByType DEFLATE image/svg+xml
AddOutputFilterByType DEFLATE image/x-icon
AddOutputFilterByType DEFLATE application/xml
AddOutputFilterByType DEFLATE application/xhtml+xml
AddOutputFilterByType DEFLATE application/rss+xml
AddOutputFilterByType DEFLATE application/javascript
AddOutputFilterByType DEFLATE application/x-javascript
AddOutputFilterByType DEFLATE application/x-httpd-php
AddOutputFilterByType DEFLATE application/x-httpd-fastphp
AddOutputFilterByType DEFLATE application/x-httpd-eruby
</IfModule>

<IfModule mod_expires.c>
ExpiresActive On

ExpiresByType image/x-icon "access plus 1 month"
ExpiresByType image/png "access plus 1 month"
ExpiresByType image/jpg "access plus 1 month"
ExpiresByType image/gif "access plus 1 month"
ExpiresByType image/jpeg "access plus 1 month"
ExpiresByType application/pdf "access plus 1 month"
ExpiresByType audio/x-wav "access plus 1 month"
ExpiresByType audio/mpeg "access plus 1 month"
ExpiresByType video/mpeg "access plus 1 month"
ExpiresByType video/mp4 "access plus 1 month"
ExpiresByType video/quicktime "access plus 1 month"
ExpiresByType video/x-ms-wmv "access plus 1 month"
ExpiresByType application/x-shockwave-flash "access 1 month"

ExpiresByType text/css "access plus 1 hour"
ExpiresByType text/javascript "access plus 1 hour"
</IfModule>

Rules for optimal web site performance

I’ve been working to improve the performance a large site at Amazon.  Steve Souders has written two excellent books that explain browser/http best practices.  A few of the rules were new to me and very helpful (flushing/mod_deflate settings, different browser techniques to defer Javascript).  The important take-away is that only a small fraction of typical page load time is bottlenecked by the server generation of a page.

High Performance Web Sites
(companion site)

  1. Make Fewer HTTP Requests
  2. Use a Content Delivery Network
  3. Add an Expires Header
  4. Gzip Components
  5. Put Stylesheets at the Top
  6. Put Scripts at the Bottom
  7. Avoid CSS Expressions
  8. Make JavaScript and CSS External
  9. Reduce DNS Lookups
  10. Minify JavaScript
  11. Avoid Redirects
  12. Remove Duplicate Scripts
  13. Configure ETags
  14. Make AJAX Cacheable
Even Faster Web Sites
(companion site)

  1. Understanding Ajax Performance
  2. Creating Responsive Web Applications
  3. Splitting the Initial Payload
  4. Loading Scripts Without Blocking
  5. Coupling Asynchronous Scripts
  6. Positioning Inline Scripts
  7. Writing Efficient JavaScript
  8. Scaling with Comet
  9. Going Beyond Gzipping
  10. Optimizing Images
  11. Sharding Dominant Domains
  12. Flushing the Document Early
  13. Using Iframes Sparingly
  14. Simplifying CSS Selectors

My first round of optimizations just went into production and our metric that measures “time from click until critical feature shows up in the browser” dropped from 5.25s to 3.5s. It’s neat to multiply the savings and see that many weeks of end-user browser load time are saved each day.

Free year of EC2 hosting on AWS

I put together my own co-located server for ChartPT, and I’ve been regretting it more and more each time AWS releases new features and drops prices.  They just announced a new Free tier today.

  • 750 hours of Amazon EC2 Linux Micro Instance usage (613 MB of memory and 32-bit and 64-bit platform support) – enough hours to run continuously each month*
  • 750 hours of an Elastic Load Balancer plus 15 GB data processing*
  • 10 GB of Amazon Elastic Block Storage, plus 1 million I/Os, 1 GB of snapshot storage, 10,000 snapshot Get Requests and 1,000 snapshot Put Requests*
  • 5 GB of Amazon S3 storage, 20,000 Get Requests, and 2,000 Put Requests*
  • 30 GB per of internet data transfer (15 GB of data transfer “in” and 15 GB of data transfer “out” across all services except Amazon CloudFront)*
  • 25 Amazon SimpleDB Machine Hours and 1 GB of Storage**
  • 100,000 Requests of Amazon Simple Queue Service**
  • 100,000 Requests, 100,000 HTTP notifications and 1,000 email notifications for Amazon Simple Notification Service**

I use S3 and CloudFront as an edge cache for StepMania.com.  I’m waiting just a little longer for the transfer costs to drop so that I can move all of the file downloads to S3 (my current S3 bill would be ~$500/mo according to the AWS calculator).

Cross-posting between WordPress, Facebook fan pages, and Twitter

I tried several different desktop clients, Facebook apps, WordPress plug-ins, and status relay services.  This is system I ended up using:

  1. Sign up for a Ping.fm account. Add your Facebook account, fan pages, and Twitter account.
  2. From WordPress: Download, install, and activate the Shorten2ping plug-in. In Shorten2ping’s settings page, set “Send Notification to Ping.fm”.
  3. Go to the Ping.fm Dashboard, click “Application Keys”, copy your API key, go to and paste it into Shorten2ping’s settings page and paste it into “Ping.fm API Key”.

WordPress now cross-posts to Facebook and Twitter, but you’re also free to do smaller status updates that bypass WordPress by initiating it on the Ping.fm site or directly on a particular service.

Automatic installations from WordPress hosted on Pair Networks

If you run WordPress on Pair Networks, automatic installations probably prompt you for FTP connection info.  The problem is that WP wants to modify files as the owner of the WP directory.  Follow Pair’s instructions to set up php-cgiwrap, and WordPress automatic installations will work.

cp /usr/www/cgi-bin/php5.cgi ~/public_html/cgi-bin/
chmod 755 ~/public_html/cgi-bin/php5.cgi

Edit .htaccess in your WordPress directory:

Action application/x-pair-sphp5 /cgi-sys/php-cgiwrap/USERNAME/php5.cgi
AddType application/x-pair-sphp5 .php

Complete instructions on Pair