The context & the issue

We have observed for some weeks many memory spikes on a client’s website, they seemed to happen in a pseudo-random way, mainly during the same 12h period daily.
The website is coded in PHP & MySQL on the server side, it is accompanied by a WordPress blog and an administration panel.

Here is how our memory usage graph looked like on cPanel.
cPanel Graph showing the random memory spikes

Spoiler: If you don’t want to read the whole article, the culprit was ModSecurity, it was solved once we deactivated it.

The step-by-step resolution

Seeing the spoiler above, I suggest you start by the end but it’s good to do it all as it gives the opportunity to improve the site.

Log check

Of course I started there, I observed the logs around the times of the spikes and slightly before to see if I could figure out the pattern and mainly the culprit but it was looking like any page could cause it. One trigger we could see is that any rise of traffic, even a small one, was generally leading to a memory spike.

PHP code review

Next step was to review the code, to update to good or more modern practice what could be done, I also updated the few external libraries that were not up to date.
Since it affected memory, I made sure I empty variables in case it would be an issue with the garbage collector. In PHP, the best way to do so seems to set the var or object property as null. it will free the memory directly:


$data = array(...);
// Do some stuff with $data
$data = null;

Security

Then I beefed up the security, I optimized portions of the code and installed CIDRAM which looks to do a good job as first barrier against potential threats.
We may want to couple it with Anti-Hammer for bots and spammers that hammer your site.
It was a good thing I did this all in all, although it did not help for our current issue and the random memory spikes continued.

Blog

The blog pages were often appearing in the raw access logs around the spikes and, even if it did not look to be the culprit, it was worth trying things on this side, mainly since the theme is homemade to match the website. I installed Query Monitor, it’s very good plugin to monitor things on WordPress if you see that your website is slow or lagging, I highly recommend it. We also installed WP Super Cache to reduce the load and mainly limit the queries, it helped “globally” but did not solve our problem.
So I tried to deactivate all the plugins, still no luck, and to switch to the default theme Twenty Seventeen … Still the same. To definitely rule it out, we eventually closed the blog for 24h, still the same. 🙁

Caching

I added a new layer of caching, the old way, by buffering the page and saving it, to serve only the static copy for the next query. Additionally or alternatively, I use PhpFastCache that is very useful. in all cases, no change… 🙁

MySQL

I checked the queries and their duration, all was looking normal on this side so I switched from MySQLi to PDO in case… and you guessed it, no more luck.

Resolution

Finally, and a little stressed as I was seriously lacking of options… I disabled all caching and since it did not help, I ended up disabling ModSecurity on cPanel and then, miracle, no more spikes!

As you can see below, we came back to a more regular memory usage after the last spike that happened less than an hour after I re-enabled ModSecurity.
cPanel memory usage after the last spike

Hope this article will help you if you’re in the same situation, I’m glad it’s fixed for my client and I hope the hosting company will be able to tune/fix ModSecurity so that we can use it again… My only regret, I wish I started by this seeing the time it took me. 🙂


Photo Credit

Sai Kiran Anagani