Avoid ‘AllowOverride All’ in Apache to limit disk I/O access

Apache has an option called "AllowOverride" which allows you to override some Apache settings via a .htaccess file you can place in a directory. In it, you can override PHP settings, create URL rewrites, ... Pretty much the basics for every website. Most installation guides will tell you to always set "AllowOverride All" in your config, I'll show you why that's a very bad idea.

Consider the following simple Virtual Host configuration in Apache.

<VirtualHost *:80>
    ServerName mysite.be
    DocumentRoot /var/www/html/mysite.be
    <Directory "/var/www/html/mysite.be">
        AllowOverride All

Thats a simple site called "mysite.be" which gets its content from the directory "/var/www/html/mysite.be" on which the AllowOverride All directive is set. Because you allow overrides in the directory "/var/www/html/mysite.be", for each lower level file that is being accessed, Apache needs to check if the configuration is not being overwritten. So, if I were to call the URL "mysite.be/content/styles/v3/style.css" for a simple stylesheet, Apache would make the following system calls.

open("/var/www/html/mysite.be/content/styles/v3/style.css", {st_mode=S_IFREG|0644, st_size=5, ...}) = 0
open("/var/www/html/mysite.be/.htaccess", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("/var/www/html/mysite.be/content/.htaccess", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("/var/www/html/mysite.be/content/styles/.htaccess", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("/var/www/html/mysite.be/content/styles/v3/.htaccess", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("/var/www/html/mysite.be/content/styles/v3/style.css/.htaccess", O_RDONLY|O_CLOEXEC) = -1 ENOTDIR (Not a directory)
open("/var/www/html/mysite.be/content/styles/v3/style.css", O_RDONLY|O_CLOEXEC) = 10

Notice how in each directory between /var/www/html/mysite.be/ and /var/www/html/mysite.be/content/styles/v3/style.css/ an extra check is being made to verify if the .htaccess file exists there. That happens for every request made to the server, since Apache needs to continuously check if there is a new .htaccess file that may overwrite the config.

In comparison, if you don't enable AllowOverride All, there are a lot less system calls needed.

open("/var/www/html/mysite.be/content/styles/v3/style.css", {st_mode=S_IFREG|0644, st_size=5, ...}) = 0
open("/var/www/html/mysite.be/content/styles/v3/style.css", O_RDONLY|O_CLOEXEC) = 10

Instead of defining your Rewrites and other configurations in .htaccess file, consider placing them directly in your Apache configuration. On busy servers, this makes quite a difference in disk performance. And if you're about to start replacing your rewrite rules in Apache, why don't you take a second to consider Nginx as webserver instead of Apache.

If you're looking for more performance gains from Apache, have a look at the blogpost titled Add ‘Options FollowSymLinks’ and avoid ‘Options SymLinksIfOwnerMatch’ in Apache to save disk I/O which gives you about the same hints in I/O performance as this post.

The Social Box

You can sign up for more updates via Twitter or Facebook below. On Twitter, I regularly talk about technology or tweet about interesting stories. Topics that don't necessarily make it to this blog. Facebook contains a steady update of blogposts and some more lightweight stories.

The @mattiasrss account has an automated RSS feed of all blogposts that get published.

Write a Comment

Do you care about the markup if your comment? You can use the following HTML tags:

<code>command</code>: command highlighting
<pre>text</pre>: pre-formatted code, can be multi-line (black background, white letters)

example <pre> tag
<blockquote>text</blockquote> quoted text
quoted example

None of this is needed of course, it's all optional!



  1. On most modern operating systems, this shouldn’t affect disk i/o much or at all. The kernel will cache the ENOENT after the first call to open() and return it immediately on subsequent calls. The only thing you’re potentially limiting is context switching (and on Linux with VDSO, even that is a negligible win).

    Did you measure any significant reduction in i/o by enabling this? It would surprise me…

  2. Philip: it does matter when your content is on a network-based filesystem (like for example NFS). And it did, as a matter of fact, have a measurable performance increase.