
Lately, I have helped a lot of clients who have 5XX errors on SiteGround, especially eCommerce sites. If you are experiencing any 499, 500, 502, 503, and 504 errors on SiteGround, please know that they are very common. I know there is nothing more frustrating than having one's site down, especially if you do not know why! If your site is down, you are truly suffering:
- You lose those precious leads
- You lose revenue and real money whether via clients, ads, or purchases from your store
- You lose trust from your potential customers
- Your SEO rankings will drop because a site with poor uptime will less likely be available when the search needs it from a search results page
Look no further! In this article, I will explain what the error codes mean, some of the terms and relevant architecture, and outline my 15 steps of what I do to address these issues.
- Understanding 500 Errors
- Solving 500 Errors
- Understanding 499, 502, 503, & 504 Errors
- Understanding the Web Hosting Architecture
- What to Expect from Managed Hosting Support
- 15 Ways of Solving 499, 502, 503, & 504 Errors
- Summary
Why is it so difficult to fix the 5xx errors on SiteGround?
On SiteGround, the problems with even identifying the 5XXs are:
- No visibility provided by SiteGround on the number of 5XXs.
- Inability to access the logs in real time via SSH, which are 15-30min behind.
- No alerts to you or from the system of any 5XXs.
Essentially, you have absolutely zero ability to identify the 5XXs without SiteGround support which they have consistently answered, "Scale the hosting plan" (which obviously benefits them). SiteGround is not really motivated to suggest anything else, so besides suggesting external experts and recommending you scale your site, I doubt you will ever get anything else from their Support team.
As a side note, SiteGround is not 100% designed and optimized for WordPress like WP Engine (which solely and only hosts WordPress). Many managed hosts that may have originally been designed for WordPress have expanded to support other types of applications like Drupal and Joomla, which also uses the same technological stack. While it makes sense to do this, fine tuning for WordPress v. Drupal v. Joomla is still different albeit very small (but these nuances matter at scale). Only when a hosting company scales their hosting do these nuances begin to show themselves. Those managed hosting companies like Flywheel that use containers (probably Kubernetes) can still claim they maintain optimization for WordPress though they've expanded into other platforms.
Can You Just Solve This For Me!?
If you do not care about how to solve this, and just want someone to do this, you are looking at between $500–$3,000. With others, it may even cost you more as they may not have a strategic approach as I do. This sort of work is considered a troubleshooting task where you are paying based on the number of projected hours worked (and must pay hourly until solved with no guarantees). The strategy laid out below is a strategic plan that can be done as a service that will give you a level of satisfaction. If you are still interested, you can hire me immediately by contacting me directly or via Codeable.
Disclaimer
Please feel free to read this article and attempt to fix your site yourself at your own risk! Please note that I cannot be held liable for what you attempt to do on your own. If you attempt to do what is outlined here and mess up your site even further, it will most likely cost you even more monies to rectify and help you. So please, please create backups of everything before moving forward with attempting to fix things yourself or with hired help.
Understanding 500 Errors
A 500 is an Internal Server Error. The server has encountered a situation that it doesn't know how to handle, and usually a 500 error is more persistent.
All hosts handle this the same way and this issue is not really germane to just SiteGround. This is also known as the WordPress White Screen of Death (though that also occurred for other reasons too). The reason for these 500 errors can be limitless, but generally the primary cause is a plugin, a missing plugin/files, or some bad code somewhere.
Now what is problematic is that SiteGround calls all their errors 500 to the end user. You only see the actual error code though the access logs. All users get the error page pictured above that says 500 - Internal Error. So the actual error code could be any one of these: 499, 500, 502, 503, or 504; all of which mean something different to a developer.
So what do you do to solve your 500 issue(s)?
If you are on a managed host (e.g., SiteGround's Cloud Hosting, WP Engine, etc.), then simply revert to a previous installation/backup. This will be the easiest by far and will not require you to hire a developer. If you are more technical or daring...then you can try some of the recommendations below. Alternatively, you can hire me or another expert or contact me directly.
If this happened right after upgrading or activating a plugin, then you simply want to deactivate the plugin either via WordPress admin or WP CLI. To do this:
- via SFTP/FTP, simply go to the
wp-content/plugins
folder and rename the plugin folder (e.g., frommy-plugin
tomy-plugin.bak
) and log into the WordPress admin plugins page (wp-admin/plugins.php
). Going to the plugins page will automatically deactivate the plugin (because it will be considered missing). - via WP CLI, at the root of the site (same place where wp-config.php is located), run
wp plugin deactivate my-plugin-slug
. For more information, see WP CLI plugin command.
If this happened right after upgrading your theme, then you want to do something similar. To do this:
- via SFTP/FTP, simply go to the
wp-content/themes
folder and rename the plugin folder (e.g., frommy-theme
tomy-theme.bak
) and log into the WordPress admin plugins page (wp-admin/themes.php
). Going to the themes page will automatically activate the default theme giving you a notice that the active theme is broken. - via WP CLI, at the root of the site (same place where wp-config.php is located), run
wp theme install my-theme-slug --activate
. For more information, see WP CLI theme command.
If you have access to the WordPress admin (meaning you can log into the site, access the plugins (wp-admin/plugins.php
) and/or themes page (wp-admin/themes.php
) and can install plugins.
- Go to the plugins page.
- Install the Health Check plugin.
- Begin troubleshooting mode via the Advanced.
- Enable your theme and check the site.
- Enable plugins one by one and check the site after every activation.
These methods will help you temporarily fix the issue and you may need to hire a developer or myself to completely fix this for you.
Understanding 499, 502, 503, & 504 Errors
There are four primary 5XX error codes that your server will be giving you: 499 Client Closed Request, 502 Bad Gateway, 503 Service Unavailable, and 504 Gateway Timeout.
- A 499 is Client Closed Request. This was originally a NGINX Error code to highlight that the client closed the request before the server could respond.
- A 502 is Bad Gateway. The server was acting as a gateway and received an invalid response from the upstream server.
- A 503 is Service Unavailable. The server is not ready to handle the request, generally as a result of being overloaded or down for maintenance.
- A 504 is Gateway Timeout. The server was acting as a gateway and did not receive a timely response from the upstream server.
There are several reasons that this is happening. First, you could be under a DDOS Attack of some kind. If this is the case, you need to implement Cloudflare or Sucuri ASAP. Second, you could have a surge in traffic that you were not expecting. Third, your resources (CPU/RAM) was not configured properly. Fourth and onward, too complicated to explain in this short-ish post.
Understanding Web Hosting Architecture
So to prevent the 5XXs, you could scale out (or expand) your resources (which costs money always) or remove load off your server by offloading traffic. To understand what I mean by offloading traffic, you need to understand the general architecture of WordPress on managed hosting platforms. On SiteGround (and many other installations), you are generally dealing with these layers:
- Web Server layer (e.g., Apache) with an ingress (e.g., NGINX)
- (Optional) Caching layer
- Web Application layer (e.g., WordPress)
- Object Cache layer (e.g., memcached and/or in-memory)
- MySQL Database layer
- Filesystem layer (see also Help Desk Geek's article on Inodes in Linux)
While I don't know SiteGround's architecture explicitly, I am fairly certain that SiteGround is using NGINX, Apache, memcached, and a database (MySQL or PostgreSQL) all on the same set of resources. There is no resource separation or isolation for preventing interference with one another (though I could be convinced that NGINX is separate from the resources as it appears to be a global thing). At scale, you would have each of these items isolated (and at super-scale a sharded MySQL, but you can ignore this as most WordPress sites don't need this level of scale).


So far, I have derived the following sequence on SiteGround:
- Traffic enters the ecosystem via NGINX (called an ingress). If you have SG Optimizer installed and enabled/configured via the SiteTools Dashboard, then NGINX will respond at that layer for all static resources (e.g., images, JS, CSS, etc.). NGINX is much, much more performant for handling these requests than Apache.
- Traffic is then handed off to the site specific stack fronted by Apache as directed by
.htaccess
file. This will catch any and all static assets that missed (for whatever reason) the NGINX ingress. - If a caching plugin like SG Optimizer or WP Rocket is installed, then the cache may intercept the traffic and respond.
- If there is no cache or cache is bypassed (called a cache miss), traffic is then handed off to WordPress to process.
- WordPress will load all its core files, plugins and theme files depending on object cache and/or memcached (if configured properly on SiteGround either via SG Optimizer or other caching plugin) fetching from the MySQL DB as needed (autoloading all [or mostly all] options).
- The Filesystem returns all the files and data to be read by WordPress.
Here's a sequence diagram that may help...hopefully.
By default, SiteGround configures http2_idle_timeout
and http2_recv_timeout
to 600
seconds, and these are not changeable. Also by default, the max_execution_time
of PHP is 120s, which is configurable via user.ini
at the root of your site (same location as wp-config.php
). So if you increase the max_execution_time
to 600
or greater then you will eventually see 499s as opposed to 5XXs since NGINX will timeout before the PHP times out.
Next, you need to understand the most vulnerable parts of WordPress. Outside the known issues with load-scripts
and load-styles
, the most vulnerable parts of WordPress are:
- XMLRPC
- Login Page
- Admin Area
- Any theme/plugin
index.php
files
If you look at your access logs, you will find that bots, people, crawlers, scrapers, etc. will be hitting those URLs trying to gain access to your site...just because they can. So you want to mitigate those as soon as you are able.
What to Expect from Managed Hosting Technical Support
If you engage the SiteGround technical support, more than likely you will be referred to external WordPress experts, like myself. At best, they will tell you to scale your site with more RAM or CPU, which obviously helps them (and really doesn't solve the problem). Running a WooCommerce WordPress site on SiteGround should be able to run well with 3-4 CPUs and 6-8GB RAMs assuming you have the appropriate plugins, architecture and caching established.
Alternatively, technical support may tell you something like the site has high IOPS (input/output operations). Simply, IOPS are read/writes of the hard disk. IOPS is the reading of the various PHP files (plugins/themes and template files) as well as the writing of cache files and MySQL transactions in order to render the site. Higher IOPS also increases memory usage and in some occasions increases CPUs (but rarely with WordPress sites). In my experience, high IOPS is characteristic of many eCommerce sites and that’s one of the few problems and is a symptom of many other potential root causes. This data and debug information is useful if you have access to monitor these processes, which on a managed host like SiteGround, you do not have.
So what do you do to solve your 499, 502, & 503 issues?
Depending on your setup, the plan I would create may differ, but generally speaking you would need to take the following actions. I attempted to organize these actions in a somewhat logical order, but depending on the situation, I would do some tasks before other tasks. Also, while these items will work almost on any host, all examples will focus almost solely on SiteGround. These actions are:
- Analyze the Logs for 499s, 500s, 502s, 503s, & 504s
- Check PHP Version
- Run WP CLI’s Doctor Command
- Properly Configure a CDN
- Disable XMLRPC
- Control Bots
- Check Memory & Compute Utilization
- Configure Proper Cron Jobs
- Use Optimized Plugins
- Optimize the Database
- Offload All Emails
- Limit AJAX Usage
- Offload Images/Assets
- Analyze WP Actions & Filters
- Determine Cache Strategy
1. Analyze the Logs for 499s, 500s, 502s, 503s, & 504s
First and foremost, you want to check all the logs to see what is impeding or bogging down the server. This exercise is entirely exploratory and will only reveal further issues that need to be addressed. Based on work I have done so far, most of the time these will reveal issues that will be addressed in subsequent items (e.g., XML-RPC, bots, etc.). Sometimes, however, they reveal gems.
Access logs are in a gzipped file, so you need to inspect them using zcat
. SSH into the site and check the logs. You can find them at www/domain.com/logs/
. You can find all the errors by using one of these commands:
# Search the gzipped file for 499s and all 5XXs. | |
zcat domain.com-YYYY-MM-DD.gz | | |
grep -P "\"\s((499)|(5\d+))\s" | |
# Search for all 499s. | |
zcat domain.com-YYYY-MM-DD.gz | grep "\" 499 " | |
# Search for all 503s. | |
zcat domain.com-YYYY-MM-DD.gz | grep "\" 500 " | |
# Search for all 503s. | |
zcat domain.com-YYYY-MM-DD.gz | grep "\" 503 " | |
# Search for all 5XXs. | |
zcat domain.com-YYYY-MM-DD.gz | | |
grep -P "\"\s5\d+\s" |
As you work through the access logs, you will find a variety of pages that are the targets of various crawlers/bots and users. More than likely, the bots are causing most of the damage. If you have a WooCommerce site, you want to check the various Woo pages as well as their AJAX calls (via wc-ajax
). Also, check your archive pages, your /feed/
pages, and the WP API (/wp-json/
) URLs.
The format of a log entry at SiteGround is a bit different. SiteGround uses a Custom Log Format combining logs from Apache and NGINX. So, in the techy world it looks like this (if you're not techy, just skip this):
In human words, it is this:
%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-agent}i\" | TLS | | |
$upstream_header_time $upstream_response_time $request_time | |
$upstream_cache_status $nocache NC:$log_nocache BP:$log_cache_bypass |
(IP Address) (identd of client or -) (userid of client or -) [ISO | |
timestamp] "(HTTP METHOD) (Request URI) (HTTP Version)" (Status Code) | |
(Object Size in bytes) "(Referer)" "(User Agent)" | (TLS Version) | | |
(Upstream Header Time) (Upstream Response Time) (Request Time) (Cache | |
Status = HIT|MISS|BYPASS) NC:(SG Specific Codes) (Binary 0/1 Cache Hit) |
For an explanation of the latter third see NGINX's Embedded Variables.
Here's a real example (with IP and domain obfuscated):
9.999.999.99 domain.com - [11/Aug/2020:14:29:37 +0000] "GET /path-to- | |
my-awesome-page/ HTTP/1.1" 503 2676 "https://domain.com/my-awesome- | |
blog/" "Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:79.0) | |
Gecko/20100101 Firefox/79.0" | TLSv1.3 | 0.037 0.041 0.041 MISS | |
W NC:000000 UP:1 |
Error Logs are currently only available via the SiteGround dashboard. According to the SiteGround Dashboard:
The error log displays the 300 most recent errors that have occurred when accessing your website over HTTP or HTTPS. Reviewing the error log can be useful for troubleshooting broken links, files and other errors.
However, this is not true at all. At the time of writing this post, they only show the 50 most recent errors. I did file a ticket with SiteGround and they have escalated the issue to their DevOps team but no timeline has been given as to when it will be fixed.
PHP Error Logs & WP Logs are only available via SSH or FTP. For PHP Error Logs, you will find a file like php_errorlog
and potentially error_log
in the folder where the PHP error occurred, which is somewhat annoying. So you want to find this via find . -name "php_errorlog"
on the SSH command line or use the find function in your favorite FTP client.
For WP Logs, check wp-content/debug.log
. If the file does not exist (and really should not on a production site), you want to temporarily enable WP_DEBUG
in wp-config.php
. This can even be done dynamically via:
// Uncomment to enable WP_DEBUG. Of course, you want to change this cookie value to something else. | |
//define( 'WP_DEVELOPER_COOKIE', 'V1AgRGV2ZWxvcGVyIGZvciBkb21haW4uY29tIGRlYnVnZ2luZyBwdXJwb3Nlcy4=' ); | |
// Enable WP DEBUG if debug query parameter exists OR the "wp_developer" cookie exists with a specific value (WP_DEVELOPER_COOKIE). | |
$wp_debug = ( | |
isset( $_GET['debug'] ) || | |
( isset( $_COOKIE['wp_developer'] ) && defined( 'WP_DEVELOPER_COOKIE' ) && $_COOKIE['wp_developer'] == WP_DEVELOPER_COOKIE ) | |
); | |
define( 'WP_DEBUG', $wp_debug ); | |
define( 'WP_DEBUG_LOG', $wp_debug ); | |
define( 'SCRIPT_DEBUG', $wp_debug ); | |
// Enable WP DEBUG_DISPLAY if debug query parameter equals "display". | |
define('WP_DEBUG_DISPLAY', ( $wp_debug && isset( $_GET['debug'] ) && ( 'display' === $_GET['debug'] ) )); |