WordPress admin Posts screen filtered to the Scheduled status, showing two posts queued at 11:00 am and 2:00 pm on 13 November 2026

3 Checks When a Scheduled WordPress Post Does Not Publish

A scheduled WordPress post that misses its slot is a cron problem until proven otherwise, and the proof is not a 200 from wp-cron.php. That request can succeed while the task inside it never runs, which is the failure that costs a day of publishing without an error anywhere.

How a scheduled post publishes

WordPress publishes a scheduled post through WP-Cron, which is not a system cron. The WordPress cron handbook says it checks a list of scheduled tasks on every page load and calls anything due during that page load. No page load and no request means no publish, which is why a quiet site misses slots and a busy one does not.

Most shared hosts fix that by calling the file on a timer, usually every 5 minutes. That entry is a separate thing from WordPress, and it can be missing, broken or pointed at a different domain.

Check 1: find out what is meant to trigger the scheduler

  1. Look for DISABLE_WP_CRON in wp-config.php. When it is set to true, page loads stop triggering the scheduler and something external has to call wp-cron.php instead.
  2. Open the host’s cron list. The usual entry is a 5-minute job requesting /wp-cron.php?doing_wp_cron on the live domain.
  3. Request that URL yourself and read the status code. A 200 says the file was reachable. It says nothing about whether a task ran.

Check 2: watch a post change, not a request succeed

The probe that answers the question is a throwaway item scheduled a few minutes ahead. A page works better than a post here, because pages never enter the feed or the post sitemap and nobody sees them.

  1. Create a page with a publish time a few minutes out and note its id.
  2. Read it back and confirm the status is future.
  3. Wait past the time, then read the page again. If it is still future, request wp-cron.php once.
  4. If the status flips to publish while you never touched the page, the scheduler works and the missing post has another cause.
  5. Delete the probe page.

Check 3: confirm the stored date is the date you meant

WordPress keeps 2 date fields. One is site local time and one is UTC, and the site timezone setting decides the gap between them. A timezone that is hours out moves every future post by the same amount, so a post set for 17:00 goes out at 11:30 with no error and nothing in a log.

The site timezone lives in Settings, General. Set it first, then re-read the post, because the stored local time does not move when you change the setting.

There is a second trap in the REST API, and it catches automated publishing. A post created with a future date that has already passed publishes immediately instead of queueing. A run that takes longer than expected therefore does not produce a scheduled post at all, it produces a live one.

What the 22 October 2026 miss looked like

On 22 October 2026 on this blog, 3 scheduled posts sat past their slot and wp-cron.php answered 200 in 0.17 to 0.46 seconds on every request. The file was reachable and fast. The tasks inside it were not running, so the 3 posts went out only when they were published by hand.

Three days later the same check proved the opposite. A post flipped from future to publish inside a run that never touched it, and its modified stamp stayed at the earlier creation time. Those 2 fields together are the clean proof. A recent modified stamp on its own proves nothing, because it can come from a content edit by anyone.

When the scheduler is fine and the post is not

An empty queue is not a cron fault. It means nothing was waiting, and publishing by hand then fixes a symptom nobody had.

The rest of the stack behaves the same way, which is why the same discipline works elsewhere. A cache that will not clear is proved by a changed page, not by a purge button. A DNS move to a CDN is proved by the answer the resolver gives, not by the dashboard. A backup is proved by a restore, not by a green tick.

The version of this that bites hardest is the one where the schedule itself expired. A recurring job that holds a single occurrence fires once and never again, and the site has nothing wrong with it at all. The same lesson shows up in a migration, where the DNS change is the last step and not the first.

Everything else on this beat sits in the WordPress care hub.

Leave a Comment

Scroll to Top