<imaginative title>

Tips, but no tricks

Tolerating & managing errors

Managing content is the heart of keeping a website alive: without content, a website is nothing, like an empty shell. But a well-managed website differs from others by the way it handles failure.

When talking about performance, you might think about enormous servers, top-notch network routers and cards, load-balancing everywhere, loads of cache, you name it. But if you are not capable of making a small setup running decently, approaching even remotely its maximum capacity, then the more you scale, the worst the power deperdition will be.

You are serving content and lack thereof, the first creating the second. You are serving failure. The difference will be how your setup tolerates it. Failure can be very resource-hungry if not properly managed. And the impact on performance can be dramatic.

As an anecdote, I was recently dealing with a Website where the ratio of 404 was hitting 30% of the daily total requests. What you do with 30% queries ending up with a useless result matter: you need to minimize resources consumption for them, to make room for queries which serve everyone's interests.

Simple, you might say, track them down and ensure they do not exist. Well, theoritically, that is true, and should be done. It is obviously simple when you are dealing with your own website over which you have full control and few formal processes to follow. But that is part of the life of the website when there could be multiple teams, each responsible for a part, not necessarily communicating at all with each other and when they do, potentially poorly. Trying to solve every source of errors is like solving a maze which walls are in a perpetual movement.

The problem of those 404 was not their volume per se, but the resources consumption coming with them.

The website was running within the framework of a CMS, which, like any CMS, uses applicative routing. This plague removes from the webserver one of its main tasks: routing requests so proper content might be served. Webservers are made to handle errors in a pretty straightforward fashion by returning either a default or a customized error page. When you are routing traffic in your application (ie in backends your webserver is talking with), you need to reimplement the webserver behavior there. You will for instance need to manage your own error pages, and you might be tempted at making them beautiful (which brings no harm or so little), but even worse: meaningful. That is, dynamic.

At the end of the process, you are generating useless content. If that does not strike you, read the previous sentence all over again, and again. And again.

So what can you do about it? Throw your CMS away? Well, that is an idea, but you are not going for it, are you? What else, then? Damage control.

  1. Intercept any content that should not be dynamic at webserver level.
    Because the human-readable URIs of you nice CMS forces you to use a blacklist approach, you need to specifically list what you want to catch. That includes of course every static resource, and every URIs your CMS is useless for.
  2. Make your dynamically-generated error pages as seamless as possible.
    Make them lose fat, or craft them as lean as possible. NO cool widget whatsoever: that is en error page, remember? If you want to be useful/friendly to your visitor, you might help him getting out of this mess with client-side interaction, or offering to redirect him to a bug-filling form, etc. There is no need to make this page useful, because the user should not be there anyway. It is not part of the normal experience.

In nginx, you might catch your template images and your content with prefix locations, like:

location /template/images/ {
}

location /pictures/ {
}

You could also go for the not recommend, less efficient way of regular expressions:

location ~* \.(css|js|png)$ {
}

You can them implement custom error pages with the error_page directive:

http {
    ...
    error_page 404 /errors/404.html;
    ...
}