WP Engine is a great web host for WordPress developers

I’ve been aware of WP Engine’s WordPress hosting offerings for quite a while now, but I only recently had a chance to dive deeply into the features and benefits they offer to WordPress developers, and I was really impressed.

(Disclaimer: I am not affiliated with WP Engine and am not being compensated by them in any way for this review. But this post contains some referral links where I may receive a small percentage of any sales that result from readers clicking through, and where readers may receive a discount on their purchase.)

Some of the things about WP Engine that stood out to me as really helpful and awesome for WordPress developers:

  1. Super-fast, comprehensive site backup snapshots and cloning. The ability to quickly make a copy of an entire production site (with a large DB and tons of media) to a staging version of that site, or just to a backup snapshot, is a huge benefit. Being able to do it at a click of a button without messing around with export/import tools, find-replace operations or similar command line intervention is just awesome, and enables all sorts of other development best practices when it comes to testing changes and having a safety net for production updates. It’s SO fast, usually completing within a minute or two, so you can make backups/clones all day long without delay. It’s better than any other site backup or environment cloning tool I’ve used in the WordPress hosting space.
  2. Deep integration with git repo management. Although the instructions and interface for setting it up needs a little expanding and polishing, the WP Engine makes it really easy to set up a git repo for a given hosting environment, where changes pushed to its main branch are quickly deployed to the associated environment. They’ve thought through the complexities of exclusions and co-existing with WordPress-initiated core/plugin/theme updates. Add in the GitHub Action to deploy to a WP Engine environment and you’ve got a really sweet development and deployment pipeline setup, all using industry best practices.
  3. Fast and powerful SSH command line access, optimized for security and WP CLI operations. WP Engine seems to understand that command line operations are an essential tool in a WordPress developer or site manager’s toolkit, and they make it really straightforward to use.
  4. Robust system status monitoring and reporting. Whereas some hosts update their system status page well after an impacting event, WP Engine seems to have theirs wired up to show a closer-to-realtime status, and that makes all the difference in not wasting time when troubleshooting or reacting to problems. I also really appreciate that they offer email, Slack and webhook-based notifications for status events, offering endless possibilities with integrating platform events into your development tools and workflows.
  5. Thoughtful tools for keeping WordPress current and secure. WP Engine clearly understands the importance of keeping WordPress core up to date and making sure no insecure plugins or themes are in place any longer than is absolutely necessary. While I think responsibility for these things generally falls to a developer and not the host, I appreciate that they’ve invested in infrastructure here, and I’m sure it benefits them and their support operations in the long run too.
  6. Great support, great communication. Whenever I’ve used the WP Engine support chat they’ve been fast, knowledgeable and straight to the point without being curt. If a question or issue needs input from another internal team, they seem to be able to do that quickly and without any resistance. Their documentation is generally well-written and organized.

In the project I was working on where I finally got to see these features directly in action, I had evaluated a variety of hosts including SiteGround, Pressable, WordPress.com Business, and WP Engine. I picked WP Engine for the above reasons and others, including their focus on WordPress-specific performance optimization.

To be clear, I’m not saying WP Engine is the best WordPress host for every use case, or even most use cases out there. Whether you’re a non-technical WordPress site owner looking for something simple and low-cost, or an enterprise-level site needing something that scales for Superbowl-level traffic with commensurate high-touch support, there are lots of great options out there that might be a better fit. (Having been a part of Automattic/WordPress.com/WordPress.com VIP and seeing the incredible investment in scalable infrastructure there, I know the details really matter at those different ends of the spectrum; I still frequently recommend their offerings too.)

But for a WordPress developer or small development team deploying custom theme and plugin code to a high-traffic site and wanting great WordPress-specific tools, systems and people to support them in that, WP Engine really stands out as worth a look.

Monitoring WordPress events and status with a custom API endpoint

Let’s say your WordPress site has some set of custom functionality that is important to the overall operation of the site, and you want to know right away if it’s not working as expected, even if the site is otherwise “up” and working fine. There could be anywhere from 0 to many things needing attention at any given time, and you don’t want to receive a flood of emails or Slack pings that you have to sort through, you just want a single alert that things are off track, and another notice when they’re back to being in good shape.

I recently handled this case using transients, a custom REST API endpoint, and the service UptimeRobot. The context for me was a set of functions that regularly retrieve information from a variety of third-party sources; most of the time it goes fine, but between network issues, changes in third-party API endpoints or HTML source code and other possible errors, occasionally these functions would break and need updating.

First, I established an error function that was called any time some aspect of my site’s custom functionality encountered a problem that might need my attention.

public static function record_event_fetch_failure( $source = null, $message = null ) {

	if ( empty( $source ) ) {
		return false;
	}

	$source         = esc_attr( $source );
	$transient_name = 'event_fetch_failure_' . $source;

	$failure_data = array(
		'count'                => 1,
		'last_error_timestamp' => gmdate( 'Y-m-d H:i:sP', time() ),
		'last_error_message'   => esc_html( $message ),
	);

	// If the transient is already there, update it.
	$event_failure_counter = get_transient( $transient_name );
	if ( false !== $event_failure_counter ) {
		$failure_data['count'] = $event_failure_counter['count'] + 1;
	}
	set_transient( $transient_name, $failure_data, 24 * HOUR_IN_SECONDS );

}

When called, this function increases the counter of the number of errors interacting with a passed third party data source, storing that counter in a transient. As my custom functions run, any failures will be recorded for up to 24 hours. If there are no additional failures to increase the counter and extend the transient expiration time, then the failure data will go away with the assumption that things are back to normal now. (You may need to adjust these assumptions for your use case.)

Then, I create a REST API endpoint on the site that allows me to monitor that failure data externally.

add_action( 'rest_api_init', function() {
			register_rest_route(
				'mysite/v1',
				'/event_fetch_status',
				array(
					'methods'  => 'GET',
					'callback' => array( $this, 'mysite_event_fetch_status' ),
				)
			);
		} );

And then a callback function to determine the content of that API endpoint:

public static function mysite_event_fetch_status() {

	$error_count = 0;

	foreach ( array( 'facebook', 'eventbrite', 'googlecal' ) as $event_source ) {
		$fail_data = get_transient( 'event_fetch_failure_' . $event_source );
		if ( false !== $fail_data ) {
			$error_count += $fail_data['count'];
		}
	}

	if ( 0 < $error_count ) {
		echo sprintf( 'There have been %d recent event fetch errors.', (int) $error_count );
	} else {
		echo 'OK';
	}
}

Now, I have a REST API endpoint available at https://example.com/wp-json/mysite/v1/event_fetch_status that will either return OK if there have been no recent problems, or an error message with a count of recent issues. I could expand that output to include more detail about which third-party services are having issues and what those issues are, but for the purposes of a red versus green monitoring setup, the basics are fine and I can look into the details when I investigate.

Finally, I set up a monitor in UptimeRobot to check that endpoint on a regular basis and notify me if there’s a problem:

UptimeRobot monitor screenshot
UptimeRobot monitor screenshot

Just for good measure, I also create an admin notice in the WordPress admin area with a little more detail about what is failing:

public static function mysite_event_fetch_admin_notice() {

	$error_count    = 0;
	$error_messages = array();

	foreach ( array( 'facebook', 'eventbrite', 'googlecal' ) as $event_source ) {
		$fail_data = get_transient( 'event_fetch_failure_' . $event_source );
		if ( false !== $fail_data ) {
			$error_count     += $fail_data['count'];
			$error_messages[] = $fail_data['last_error_timestamp'] . ': ' . $fail_data['last_error_message'];
		}
	}

	if ( 0 < $error_count ) {
		echo '<div class="notice notice-warning">';
		echo sprintf( '<p>There have been %d recent event fetch errors.</p>', (int) $error_count );
		echo '<ul>';
		foreach ( $error_messages as $message ) {
			echo sprintf( '<li>%s</li>', esc_html( $message ) );
		}
		echo '</ul>';
		echo '</div>';
	}
}

add_action( 'admin_notices', array( $this, 'mysite_event_fetch_admin_notice' ) );

All put together, I will now receive alerts as configured in UptimeRobot when my custom functions have issues.

You could go the typical route of generating an email or Slack message about each problem, but in my experience this can quickly create a lot of one-off monitoring and alerting configurations in your life, and that can lead to you missing important information or being desensitized to the notices. Instead, I find it’s worth trying to manage all of my time-sensitive notifications across all of my various projects and services in one place where possible, and UptimeRobot or similar services offer a lot of flexibility for that.