Fixing WordPress scheduled posts that fail to publish

How to fix WordPress posts stuck on "Missed schedule" by checking your timezone, diagnosing WP-Cron loopback failures and replacing WP-Cron with a real server cron job.

You scheduled a post for 9am, and at 9am nothing happened. On the Posts screen, it's still sitting there, now labelled Missed schedule in red,1 and it'll stay that way until something nudges it.

It's one of the most common WordPress complaints, and almost every case comes down to the same cause: WordPress doesn't have a clock running in the background. It relies on visits to your site to check whether anything is due.

Why scheduled posts get missed

WordPress handles scheduled tasks through a system called WP-Cron. Despite the name, it isn't the cron scheduler built into your server. It's a list of tasks with due times stored in your database, and it only gets checked when someone loads a page on your site.2

When a visitor arrives, WordPress sends a background request to wp-cron.php on your own site, which runs anything that's overdue. Publishing a scheduled post is one of those tasks.

So a scheduled post publishes on the first page view after its scheduled time, not at the scheduled time itself. On a busy site the difference is seconds. On a quiet site, a post scheduled for 3am might not go out until someone visits at 9am. And if that background request is being blocked, it may never go out at all.

That leaves three things to check, in order: whether WordPress has the right time, whether WP-Cron can reach your site and whether you'd be better off replacing WP-Cron with a real server cron job.

Check your site's timezone

Before assuming anything is broken, check the schedule is what you think it is.

Go to Settings → General and look at the Timezone setting. WordPress lets you choose either a city or a fixed UTC offset.3 A fixed offset such as UTC+1 doesn't change for daylight saving time, so twice a year your scheduled times shift by an hour. Choosing a city avoids that. For a UK site, London switches between GMT and BST automatically.

Check the current time WordPress shows next to the setting. If it doesn't match the actual local time, posts are being scheduled against the wrong clock and will appear to publish early or late even when WP-Cron is working perfectly.

Check WP-Cron can reach your site

WP-Cron relies on a "loopback" request: your server making a request to your own site. Plenty of things can block loopback requests, and when they're blocked, WP-Cron stops quietly.

The quickest check is Tools → Site Health. WordPress tests loopbacks and scheduled events automatically and reports problems such as "Your site could not complete a loopback request", "A scheduled event has failed" or "A scheduled event is late".4

WordPress's documentation says the most common cause of loopback failures is a plugin or theme conflict.5 Other common causes include:

  • Password protection on the whole site. Staging and development sites are often behind a username and password prompt, which blocks the loopback request. This is a very common reason scheduling breaks on staging sites.
  • A security plugin or firewall treating your server's own request as suspicious and blocking it. The same rules often cause 403 forbidden errors elsewhere on the site.
  • Server firewall rules that stop the server connecting to its own public address. Only your host can check this.
  • Wrong site addresses in WordPress's settings or in WP_HOME and WP_SITEURL, so WordPress tries to call itself on an address that no longer works. This often happens after a move to HTTPS, covered in our guide to fixing mixed content.
  • Aggressive caching serving a stored response to wp-cron.php instead of running it.

To test directly, visit https://yoursite.com/wp-cron.php?doing_wp_cron in your browser (with your own address). A working site usually shows a completely blank page. An error, a login prompt or a security challenge suggests something is getting in the way.

Check whether WP-Cron has been switched off

Look in wp-config.php for this line:

define( 'DISABLE_WP_CRON', true );

If it's there, WP-Cron's visitor-triggered checks have been switched off on purpose. That's a sensible setup, but only if a real server cron job has been set up to replace them, as described below. If the line is there and there's no server cron job, scheduled tasks won't run at all.

If you find the line and no replacement cron job exists, either set up the cron job (the better option) or, with a copy of the file saved first, remove the line.

Replace WP-Cron with a real cron job

This is the lasting fix, and it's what I set up on sites I maintain. Rather than relying on a visitor turning up at the right moment, the server runs WordPress's task list on a fixed schedule. WordPress's own documentation describes this approach.2

Many managed WordPress hosts already do this for you. Check your host's documentation or ask their support first, so you don't end up with two running. If your host will set it up for you, that's the safest option.

If you're setting it up yourself, first switch off the visitor-triggered checks by adding this to wp-config.php (with a copy of the file saved first), above the line that reads /* That's all, stop editing! */:2

define( 'DISABLE_WP_CRON', true );

Then, straight away, create a server cron job that calls wp-cron.php every few minutes. Until it's in place, nothing scheduled will run. Most hosting control panels have a Cron Jobs section. A job that runs every five minutes looks like this, with your own address in place of yoursite.com:

*/5 * * * * wget -q -O - "https://yoursite.com/wp-cron.php?doing_wp_cron" >/dev/null 2>&1

If WP-CLI is available on your hosting, this version runs the tasks directly rather than through a web request, so it isn't affected by firewalls, security plugins or password prompts:6

*/5 * * * * cd /path/to/your/wordpress && wp cron event run --due-now >/dev/null 2>&1

Replace /path/to/your/wordpress with the actual location of your site on the server (your host can tell you). Every five minutes suits most sites: often enough that posts go out close to their scheduled time, but not so often that it adds noticeable load.

If you run WooCommerce, this also keeps its background task queue moving. Our guide to past-due scheduled actions in WooCommerce covers that queue.

Rule out plugin conflicts

If loopbacks work, the timezone is right and cron is running, a plugin may be interfering with scheduling itself.

Deactivate plugins one at a time, scheduling a test post a couple of minutes ahead after each, and see whether it publishes. Deactivating plugins switches their features off for visitors too, so do this on a staging copy or at a quiet time if you can, and reactivate everything once you've found the cause.

Security and caching plugins are the usual suspects, since both sit in front of the request WP-Cron depends on. Performance plugins that delay or switch off WP-Cron are worth checking too. On a busy site, scheduled tasks piling up can also add to server load, and our guide to fixing 502, 503 and 504 errors covers that side.

Publish the posts that already missed their slot

A post marked Missed schedule won't publish itself once its time has passed, even after you've fixed the cause. You'll need to publish it by hand.

Open the post, change the publish date to now and click Publish. For a handful of posts, that's quick enough.

For a long backlog, you can select the posts on the Posts screen, choose Edit from the bulk actions menu and set the status to Published. Bulk publishing can leave posts with their original scheduled dates, which may put them in a different place in your archive than you expect, so check the dates afterwards. Publishing also triggers anything linked to new posts, such as email newsletters or social media sharing, so check those before publishing a large batch.

Need help with WordPress scheduling?

If scheduled posts keep missing their slot after all of this, the cause is usually at server level: blocked loopbacks, a strict firewall or a host that handles cron differently. Your host can check these. My WordPress maintenance and support plans include monitoring scheduled tasks so problems get caught early, and my WordPress development service can sort out a stubborn server configuration.


  1. class-wp-posts-list-table.php, WordPress source code on GitHub. ↩

  2. Hooking WP-Cron into the system task scheduler, WordPress Plugin Handbook. ↩ ↩ ↩

  3. options-general.php, WordPress source code on GitHub. ↩

  4. class-wp-site-health.php, WordPress source code on GitHub. ↩

  5. Loopbacks, WordPress Advanced Administration Handbook. ↩

  6. wp cron event run, WP-CLI Commands. ↩

Adam Greenough

Written by Adam Greenough

Freelance web developer with over 15 years of experience building and fixing WordPress sites. I work with businesses across the UK on everything from emergency support to full builds.

Need emergency WordPress support today?

If your site is down, hacked or throwing errors, send me the details and I will assess the problem quickly. Support starts from £50, you will get a fixed quote before any work begins, and if I cannot fix the issue, you will not pay.