How to bring down a poorly deployed WordPress (and how to stop it from happening)

I used to hate WordPress (and Apache). When x5315 and I first got a cheap VPS from XenEurope (I recommend them, but don’t be as stingy as us!) it had 128MB of RAM. We both wanted WordPress blogs. Thus what ensued was a performance nightmare. For the record, we ended up using lighttpd and FastCGI instead of Apache, but most people use Apache so that’s what I’m going to focus on here.

Does your cloud server have 2GB of RAM?

Apache by default has ridiculous settings. It will try to serve 150 clients simultaneously before it starts making new clients wait. Each one of those 150 clients will be a memory guzzling Apache process that will stay alive for 15 seconds (strictly speaking only 100 will stay alive at any one time) after the client has finished and will hang around for 300 seconds before timing out if the client is slow. Not only that, but Apache will always try to keep around 10 processes spare for serving new requests.

New Apache processes serving this blog appear to take anything from 5-15MB of RAM. At worst, that means that if Apache tries to maintain 150 concurrent processes it will use over 2GB of RAM. Way more than the average VPS, cloud server, EC2 instance, whatever. When this happens, Linux will start swapping out processes to disk, and your server will basically grind to a halt. In most situations, you will struggle to even SSH in to the server.

Try it yourself

Why not try ‘sieging’ your favourite WordPress blog you think is run on a tiny EC2 instance a quick test WordPress installation from your computer (install siege, available in all good package repositories) to any sort of VPS or cloud instance (Rackspace are good, and they are faster to set something up with than Amazon EC2):

siege -c 250 http://path.to.blog/

That command tries to run 250 concurrent requests (repeatedly) against the URL. Essentially a DoS attack (that’s why you should run it on your own installation, otherwise it’s illegal!).

Like you with your test installation, most people wont have configured Apache properly. At best others may have installed some sort of caching plugin (which wont help you against Apache’s memory guzzling tendencies). Your server will fall to its knees.

So how do you fix it?

By keeping Apache on a really tight leash. Here’s the relevant lines from the Apache config running this blog:

    StartServers          2
    MinSpareServers       2
    MaxSpareServers       6
    MaxClients           10
    MaxRequestsPerChild   300
  • StartServers is fairly self explanatory. We’re restricting Apache to just 2.
  • MinSpareServers is the number of processes Apache will try and keep around to handle incoming requests.
  • MaxSpareServers is the number of processes Apache will keep around after serving requests before killing some off. It’s not hugely important what value you have this at – in fact a higher value will probably help reduce cache thrashing (no idea though)
  • MaxClients is the important one. Set it to something low, here I’ve set it to 10, but if you have a hefty WordPress site (e.g. lots of plugins) you may want to set it as low as 5 on a server with only 256MB RAM for example.
  • MaxRequestsPerChild is the number of clients a process can serve before it dies and a new one is created in its place. Setting this to a reasonable value makes Apache ‘refresh’ old processes which have probably consumed a lot of RAM.

Technical note: This config assumes you are using prefork MPM (the default), rather than worker threads.

For added performance, reduce the KeepAliveTimeout to something less than 15.

With these settings, Apache will at least avoid killing your server. If your blog is getting a large number of requests (congratulations!), some readers may have to wait a few seconds or even get rejected, but that’s just the way it is, and that’s better than not being able to even SSH in to your server to fix things!

Edit: _pdeschen on Hacker News suggested that for real performance, you could try nginx. I also recommend nginx (I use it for all my other hosting) and he has a blog post about getting WordPress to work with nginx. Thanks!

This entry was posted in Blog, Noteworthy. Bookmark the permalink.
  • Anonymous

    I’m running WordPress on nginx on a weakling VPS, it is pretty good (though I have to stress test it more, as your post shows, thanks!). The current bottleneck seems to be php anyways, I’m trying to find some way to improve that.

    • http://jalada.co.uk Jalada

      Do you have lots of plugins installed? That can really affect PHP performance with WordPress. Have you installed a PHP accelerator? http://en.wikipedia.org/wiki/PHP_accelerator I recommend XCache but not for any scientific reason – best to do benchmarks yourself (you can use siege for that, when you quit siege it tells you the average concurrency, use that as a gauge)

      • Anonymous

        As much as I could benchmark it, it is more due to the lack of available memory and it swapping in-and-out occasionally (256Mb does not go far, but you probably know much better than me). Not too many plugins, pretty much the basics, and SuperCache saves the day mostly :)
        XCache is indeed on the shortlist of things to try, and planning to give HipHop a chance too. Thanks for the recommendation.

        • http://jalada.co.uk Jalada

          Check out http://core.trac.wordpress.org/ticket/14642 for info about HipHop.

          If you’re using nginx, what are you using for your PHP? If you used an external PHP FastCGI server you could restrict the number of processes and that should avoid swapping in the same way that my configuration avoids Apache swapping.

          • Anonymous

            I have CentOS on a VPS. I kinda regret now choosing CentOS – good to learn a new system but that one has so many near-obsolete packages that it is amazing (maybe I got spoiled by my regular Arch Linux’s common 0-day update)…

            So I had PHP 5.1.6, and used Spawn-FCGI + socket. That game me 503 errors quite often… I upgraded PHP to 5.3.5 and now use the built-in PHP-FPM + socket + Zend + tweaked nginx fastcgi_params + SuperCache with rewrite rules. It feels much snappier and it survives the siege quite well compared to the small memory and lack of CPU power. :)

            Thanks for the link, I’ll try that out too…

  • http://twitter.com/teren_teh Teren Teh

    Thanks for the post! While I didn’t really have problems running Apache with WordPress (256MB RAM maybe?) but when running other apps, my whole server locked up. I’d say definitely look at nginx or lighttpd for small VPS instances.

    Here’s an issue I had with WordPress and nginx though, I’m using the fcgi with WordPress but every so often the processes die off. Does anyone have an idea why?

    • http://jalada.co.uk Jalada

      All of the processes? I never have problems with my fcgi server & nginx. I’m using an external process to spawn and monitor the fastcgi processes, how are you doing it?

  • Pingback: Sysadmin Sunday #17 « Boxed Ice Blog

  • Anonymous

    While I did suggest to use nginx as a caching proxy front end, I think your approach/technique should be a first step toward optimization! And you highlighted quite a few nice tricks here!

    While I don’t have any other alternatives, siege seems limited in terms of concurrency (can’t get pass the 300 mark and I have 4gb RAM). Does anyone have alternatives?

    300 concurrent clients is handled too smoothly with my setup so I wanted to really give it a shot with some more :-)

    • http://jalada.co.uk Jalada

      Maybe run siege from more than one computer?

      300 clients is a reasonable amount of bandwidth – make sure you’re not saturating your pipe anyway. Otherwise…maybe growing your own in a suitable language would be a good choice (Scala or Erlang would be my suggestions).

  • http://andr.esmejia.com Andrés Mejía

    I didn’t know about Siege. I’ve been using Apache Benchmark (http://httpd.apache.org/docs/2.0/programs/ab.html) all this time but Siege has nicer colored output which makes me want awesome hallucinations! (Think LSD).

    • http://jalada.co.uk Jalada

      I’ve used Apache Benchmark too. I prefer siege because it’s so damn simple and has a few useful command line options.

  • Pingback: Post to BizDevTalk 02/08/2011 — Business Developer Talk

  • Pingback: Optimize Your WordPress Blog With These Tutorials And Plugins | Top Design Magazine - Web Design and Digital Content

  • Kev DJR

    Thank you for your knowledge. I’ve been struggling with my 512MB MediaTemple DV server. I have 2 WordPress websites and 3 others normal sites. About 10 emails running at the same time.

    You did not only solved my wordpress issue but you did solve my whole entire server lock up issue.

  • zane kolnik

    I’ve adjusted httpd.conf files before to optimize memory, but never as a security measure.
    Wouldn’t a better way be to have a security feature where when one IP sends X amount of request they are banned or your throttle them? 

    • http://jalada.co.uk Jalada

      That’s fine but this is optimisation for a situation where your blog receives a sudden large amount of genuine traffic for example if you are linked to from a popular blog. In that situation each connection will be from a different IP anyway, and you want them to see your content, not block them!