This website is running on a free tier AWS EC2-micro instance. The power of this micro instance is not much, but with a little tweaks the performance is more then enough to run a WordPress website. For analyzing the performance I use New Relic and GTMetrix. By tweaking Apache and configuring PHP.ini I have created a stable well performing website.
After creating a EC2 instance, based on the Amazon Linux AMI with the t2.micro type, I ran into low memory issues. The free micro instance contains 1 GB memory which isn’t much for a web server. Therefor my website was unavailable and to resolve this I had to stop/start the instance from the AWS Console. But this was only a temporary solution. After a couple days the same problem occurred.
Analyzing the problem
I started to analyze this problem with New Relic. The dashboard showed me that we Physical Memory exceeded 100% and after that it went to 0% meaning the instance was stopped. All other metrics were OK; the CPU usage never exceeded 10% and Disk I/O utilization and Network I/O were fine.
When reviewing the memory use by processes the httpd process topped the list. Yes, it should be on top, it`s a web server. But 90% of the memory is in constant use, that is not good.
I had to find a solution to this memory use, maybe a way to max the use for this httpd process. I found two interesting articles for this problem suggesting some tweaks:
The tweaks for Apache needs to be done in the /etc/httpd/conf/httpd.conf file. This is the main configuration for Apache. See the bottom of my article for a sample of the config file. Edit this file setting the following values:
1. Timeout: 20 sec
The default Apache timeout is set to 60 seconds, but this is way to long. When a page did not load within 20 seconds I say there is something wrong.
2. KeepAlive: On
This setting is debatable, but I have enabled it for best website performance. GTMetrix is advising you to enable this.
3. MaxKeepAliveRequests: 50 and KeepAliveTimeout: 10
If you enabled KeepAlive on your low memory server, you should reduce the MaxKeepAliveRequests and KeepAliveTimeout. I recommend setting the MaxKeepAliveRequests to 50, representing max 50 requests per sessions, which is more then enough. I also recommend to set the KeepAliveTimeout to 10 seconds. The article Tuning Apache for a low memory server does some more explaining on the values.
4. Prefork MaxClients: 10
Prefork is where the real magic happens. This is where we can tell Apache to only generate so many processes. In the New Relic view of processes the count represented the number of processes, which is 20. By reducing this to 10 we reduce the total memory usage of the httpd process
5. FileETag: None
GT Metrix is recommending to set FileETag to None. By removing the ETag header, you disable caches and browsers from being able to validate files, so they are forced to rely on your Cache-Control and Expires header set in you .htaccess file.
Of course there is more, but for me the result now is fine. But if you really want to push it you can eliminating unnecessary Apache modules from the configuration and recompile Apache, optimizing for memory consumption.
Timeout 30 KeepAlive On MaxKeepAliveRequests 50 KeepAliveTimeout 10 <IfModule prefork.c> StartServers 3 MinSpareServers 2 MaxSpareServers 5 MaxClients 10 MaxRequestsPerChild 1000 </IfModule> # if you are using workers, update the IfModule worker.c section similarly. <IfModule worker.c> StartServers 3 MaxClients 10 MinSpareThreads 25 MaxSpareThreads 75 ThreadsPerChild 25 MaxRequestsPerChild 1000 </IfModule>
6. Use Production PHP.ini
After I had created the AWS instance I replaced the PHP.ini from the one PHP.net is presenting as thé Production PHP.ini. You can download it from Github. This ensures me that the default settings are set for a Production environment and not for debugging.
7. Set Expire headers
GT Metrix is very strict on caching and recommend to set Expire Headers in your .htaccess file. Combined with disabling the ETag header this results in the best way for browsers to cache content.
<IfModule mod_expires.c> <FilesMatch "\\.(jpe?g|png|gif|js|css)$"> ExpiresActive On ExpiresDefault "access plus 1 week" </FilesMatch> </IfModule>
GT Metrix is rating AA
Call me a fanatic, but a GT Metrix rating of AA is making me smile 😀
Great performance and running stable
The tweaks above really helped me in making my AWS instance running stable and smooth. And although this is a t2.micro machine with low memory, I am still getting a great performance rating for GT Metrix. Both making me confidence in serving the best end user experience possible.