Uptime monitoring for WordPress sites

Monitor the paths that take the money, not the homepage: a health route that fails when WooCommerce is off or wp-cron and the renewal queue fall an hour behind, plus the Store API your checkout calls, each checked from outside with a Telegram alert.

A WordPress business earns its money on paths the homepage never touches: the checkout, the member login, the booking form, and the jobs that run with nobody watching, like subscription renewals, membership expiry and reminder emails. A homepage check sees none of that, and a page cache keeps it green while all of it fails.

Three failures cost a store the most, and none of them changes the status code of the homepage.

  • wp-cron stops. WordPress runs scheduled events only when PHP serves a request, and a cached page does not count. Set DISABLE_WP_CRON without adding a server cron, or let a firewall block the loopback request, and nothing scheduled runs again.
  • The renewal queue stalls. WooCommerce Subscriptions charges renewals through Action Scheduler, which runs off wp-cron once a minute. When cron stops, renewal orders stop, and every subscription still says Active.
  • A night-time auto-update breaks checkout. Since WordPress 6.6, a plugin auto-update that throws a fatal error on the homepage is rolled back. One that breaks only checkout or login stays installed, and theme updates have no rollback at all.

A health route that knows about the money

wp-content/mu-plugins/shop-health.php
<?php
add_action('rest_api_init', function () {
    register_rest_route('shop/v1', '/health', [
        'methods' => 'GET',
        'permission_callback' => '__return_true',
        'callback' => function () {
            $hourAgo = time() - HOUR_IN_SECONDS;
            $failing = [];

            if (!class_exists('WooCommerce')) {
                $failing[] = 'woocommerce inactive';
            }

            $oldestDue = array_key_first(wp_get_ready_cron_jobs());
            if ($oldestDue !== null && $oldestDue < $hourAgo) {
                $failing[] = 'wp-cron an hour behind';
            }

            $lateActions = function_exists('as_get_scheduled_actions')
                ? as_get_scheduled_actions([
                    'status' => 'pending',
                    'date' => $hourAgo,
                    'date_compare' => '<',
                    'per_page' => 1,
                ], 'ids')
                : [];
            if ($lateActions) {
                $failing[] = 'scheduled actions an hour behind';
            }

            $response = new WP_REST_Response(
                ['failing' => $failing],
                $failing ? 503 : 200
            );
            $response->header('Cache-Control', 'no-store');
            return $response;
        },
    ]);
});

Must-use plugins load on every request and have no Deactivate link. The route answers 200 with an empty list, or 503 with the names of what failed. Logdash puts the response body into the Telegram alert, so the message says wp-cron an hour behind, not only 503. On a membership or booking site, swap WooCommerce for the class of the plugin that takes the payments.

Three URLs worth watching

  • The health route, at /wp-json/shop/v1/health.
  • The Store API, at /wp-json/wc/store/v1/products?per_page=1. It is public, needs no key, and is the same API the Cart and Checkout blocks call.
  • The homepage, for DNS and hosting failures that happen before WordPress runs at all.

That is 3 services, so the free Hobby plan covers them with checks every 5 minutes. A store that takes orders at night is worth Builder at $9 a month for 1-minute checks, or Pro at $15 for every 15 seconds. Each check is also an uncached PHP request, which nudges wp-cron on a quiet site. If the route still reports cron behind, something blocks the loopback.

Why not a heartbeat for wp-cron? Logdash push monitors are Pro only and expect a ping every 15 seconds, with no schedule and no grace period. That fits a worker loop, not an hourly job. The health route turns a late job into a status code that a normal check reads, on every plan.

  1. Install the route Upload shop-health.php to wp-content/mu-plugins and open /wp-json/shop/v1/health. You should see {"failing":[]}.
  2. Add three monitors and Telegram Create a service each for the health route, the Store API and the homepage. Add @logdash_uptime_bot to a Telegram chat, send it the passphrase and tick that chat on all three.
  3. Switch WooCommerce off on staging On a public staging copy, deactivate WooCommerce. The next check gets a 503, and a Telegram alert reaches you naming the health route, with woocommerce inactive in the message.

Logdash vs UptimeRobot for a WordPress store

FeatureLogdashUptimeRobot
Free monitors5 services50 monitors
Free check intervalEvery 5 minutesEvery 5 minutes
1-minute checks$9 a month on Builder, 20 services€10 a month on Solo, 10 monitors
Fastest interval15 seconds for $15 a month30 seconds for €41 a month on Team
Page must contain "Add to cart"No, status code onlyKeyword checks on every plan
Alert channelsTelegram and webhook, freeEmail free, Telegram and SMS from Solo

When UptimeRobot is the better pick

  • You would rather check that a product page still shows Add to cart than install a PHP file. Keyword checks do that on the free plan.
  • You want alerts by email or SMS. Logdash sends Telegram messages and webhooks only.
  • You want more than 5 URLs watched for free.
Why are my WooCommerce subscription renewals not processing?
Most often because wp-cron stopped. Renewals are Action Scheduler actions that run off wp-cron, so when cron stalls they sit as pending under WooCommerce, Status, Scheduled Actions while the subscription stays Active. The health route above turns that into a 503 within the hour.
Does wp-cron run if nobody visits the site?
No. It runs when PHP serves a request, and a cached page does not count. An uncached monitor check counts, and a server cron that calls wp-cron.php every few minutes is the reliable fix.
Can a plugin auto-update take down my WordPress site?
Yes. Since WordPress 6.6, a plugin auto-update that causes a fatal error on the homepage is rolled back. An update that breaks only checkout or login stays installed, and theme auto-updates have no rollback.
How often should I check my WooCommerce store?
Every minute once it takes orders while you sleep. Builder does that for $9 a month across 20 services, and the free plan checks every 5 minutes.

Point it at your own URL and watch it for real.