You schedule a post to publish at 9 AM, check the site at 9:05, and it is still showing as Scheduled. Or scheduled posts occasionally publish hours late. Or they never publish at all and stay stuck in Scheduled status forever. WordPress scheduled posts depend on the WordPress cron system (WP-Cron) to trigger at the correct time, and WP-Cron has a fundamental design limitation that makes it unreliable on low-traffic sites. This guide covers why scheduling fails and every method for fixing it. This fits into the wider topic we cover in our WordPress Errors Complete Guide.
WordPress Scheduled Posts — How WP-Cron Works and Why It Fails
WordPress scheduled posts are processed by WP-Cron, WordPress’s built-in task scheduling system. WP-Cron is not a real server cron — it does not run on a clock. Instead, it runs whenever a page on the WordPress site is loaded. When any visitor (or the site itself) loads any page, WordPress checks whether any scheduled tasks are overdue and executes them.
This design means WordPress scheduled posts can only publish when someone visits the site. On a high-traffic site receiving thousands of visitors per hour, this works reliably — a post scheduled for 9:00 AM publishes at 9:00 AM or within seconds because a visitor will always load a page at that exact minute. On a low-traffic site that receives only a few visitors per day, the post may sit in Scheduled status for hours until the first visitor triggers WP-Cron. A site in maintenance mode, a site with aggressive page caching that serves all requests without hitting PHP, or a site that was temporarily inaccessible at the scheduled time all produce missed scheduled post publishing for the same underlying reason — no PHP execution at the scheduled time means no WP-Cron execution.
Verify that WP-Cron is functioning: install the WP Crontrol plugin → navigate to Tools → Cron Events. The list shows all scheduled WordPress cron events including wp_scheduled_delete, wp_update_themes, and any custom events from plugins. If the list is empty or shows events that are significantly overdue (more than an hour past their scheduled time), WP-Cron is not firing. The plugin also shows the last time cron executed — if it is many hours ago on a site that should have traffic, cron is broken. Our guide on diagnosing WordPress site down events covers the server access issues that can prevent WP-Cron from executing even on sites with traffic, when caching or server configuration prevents PHP from running on each page request.
Fixing Missed Scheduled Posts With Real Server Cron
The most reliable fix for WordPress scheduled posts not publishing is replacing WP-Cron with a real server cron job that runs on a clock rather than depending on visitor traffic. This is a five-minute setup on any hosting account with cPanel or SSH access.
Set up real cron to fix WordPress scheduled posts: in cPanel → Cron Jobs → Add New Cron Job → frequency: every minute → command: wget -q -O - https://yoursite.com/wp-cron.php?doing_wp_cron or on a VPS with PHP CLI: php /path/to/wordpress/wp-cron.php. After adding the server cron job, disable WP-Cron’s automatic execution to prevent duplicate runs: add define('DISABLE_WP_CRON', true); to wp-config.php. With DISABLE_WP_CRON true, WordPress scheduled posts now rely on real server timing on every page load — the server cron handles all scheduled tasks on the minute interval set in cPanel. WordPress scheduled posts now publish within one minute of their scheduled time regardless of site traffic, maintenance mode, or caching configuration.
Verify cron is working: schedule a test post for 5 minutes in the future → wait → confirm it publishes at the correct time. Also check WP Crontrol after 2–3 minutes: all cron events should show last-run times within the last minute. If the server cron wget command fails (returns an HTTP error), it may be because the hosting server cannot reach its own domain via HTTP (loopback request restriction). In this case, use the PHP CLI version instead: find the PHP binary path (which php in SSH) → use the full path in the cron command. Contact hosting support if neither approach works — some shared hosting environments restrict both outbound wget and PHP CLI cron jobs, requiring the hosting provider’s own cron implementation to trigger WordPress cron correctly.
Diagnosing and Republishing Missed Scheduled Posts
When WordPress scheduled posts are stuck — showing Scheduled status past their publish date — they need to be manually triggered or bulk-republished after the underlying cron issue is fixed. Missed posts do not automatically republish when cron is restored.
Manually publish a stuck scheduled post: edit the post → change the publish date to a time in the past (or switch to “Publish immediately”) → Update. WordPress publishes the post immediately. For bulk-fixing many missed scheduled posts, install the Missed Schedule Posts Publisher plugin → the plugin scans for overdue scheduled posts and publishes them all in one action. Run it once after fixing the WP-Cron issue to clear the backlog of stuck posts. After clearing the backlog, the plugin can be deactivated — the server cron setup prevents future missed posts without an always-on plugin.
The Publish Missed Schedule plugin (free, WordPress plugin directory) adds a secondary publishing mechanism alongside WP-Cron: every time any page loads, it checks for overdue WordPress scheduled posts and publishes them if WP-Cron missed the scheduled time. This plugin-based approach is easier to set up than server cron for non-technical users and dramatically reduces the delay for missed posts — instead of waiting for a visitor to load the exact page that triggers WP-Cron, the plugin checks on every page load. The limitation compared to real server cron: it still depends on visitor traffic and may not work during off-hours on low-traffic sites. For sites without server cron access, this plugin is the most practical alternative to leaving WordPress scheduled posts dependent on the unreliable default WP-Cron timing.
Scheduled Posts and Timezone Configuration
A common and easily missed cause of WordPress scheduled posts publishing at the wrong time is an incorrect timezone setting — posts appear to publish late or early by a consistent offset equal to the difference between the configured timezone and the intended timezone.
Verify the WordPress timezone: Settings → General → Timezone. WordPress stores all scheduled times in UTC internally and converts to the configured timezone for display in the admin. If the timezone is set to “UTC+0” but the intended timezone is “America/New_York” (UTC-5), a post scheduled for 9:00 AM Eastern Time is stored as 9:00 AM UTC and publishes at 4:00 AM Eastern — a 5-hour offset. The fix: select the correct named timezone from the dropdown (use named timezones like “America/New_York” rather than UTC offsets — named timezones automatically adjust for Daylight Saving Time, while UTC offsets do not). After correcting the timezone, any existing WordPress scheduled posts retain their stored UTC time — verify scheduled posts in the edit screen and adjust their publish times if they were scheduled with the incorrect timezone.
Server timezone versus WordPress timezone mismatch creates a confusing scheduling environment where the WordPress admin shows one time but the server executes at another. The server’s timezone is set at the OS level (typically UTC on most hosting servers) and affects what time the server cron job executes relative to the times shown in the WordPress admin. The server cron job should be configured in UTC (the server’s timezone) while WordPress shows times in the configured local timezone. This is handled automatically — when the server cron triggers wp-cron.php, WordPress uses its own timezone configuration to determine which scheduled tasks are due, independently of the server’s timezone. The server cron job’s only job is to trigger WordPress cron execution at regular intervals; WordPress itself manages all the timezone-aware scheduling logic. Our guide on fixing WordPress post not saving covers the autosave and scheduling system that interacts with WordPress scheduled posts when save failures prevent scheduled posts from being correctly recorded in the database.
Advanced Scheduling — WooCommerce, Editorial Workflows, and Recurring Posts
WordPress scheduled posts functionality extends to more advanced publishing workflows that the default scheduling system does not cover natively. WooCommerce product scheduled sales, editorial approval workflows, and recurring content publication each require specific plugins or custom code.
Schedule WooCommerce product availability: products can be scheduled to appear and disappear from the shop at specific times using WooCommerce’s built-in scheduled sale pricing (set a sale price with start and end dates) or by scheduling the product’s published status using the same WordPress scheduling system. For seasonal product launches or limited-time availability, this combination covers most WooCommerce scheduling needs. For complex promotional campaigns — products appearing in multiple categories, bundles being created and removed, coupon codes activating automatically — WooCommerce’s built-in scheduling plus cron-triggered custom code handles the workflow more reliably than third-party scheduling plugins.
Editorial calendars for managing WordPress scheduled posts across a team of writers are provided by the EditFlow and PublishPress plugins. Both add a visual calendar view of all scheduled content, drag-and-drop rescheduling, editorial status states (Draft → Pitch → Pending Review → Scheduled → Published), and email notifications for each status change. For multi-author publications where content planning and scheduling is a collaborative process, an editorial calendar plugin converts the WordPress post list’s flat scheduled view into a genuinely useful production planning tool. PublishPress also includes future scheduling improvements — the ability to perform automated actions on posts at scheduled times beyond just publishing, including moving posts between categories, changing post status, updating custom field values, and sending notifications. Reviews from the WordPress publishing community confirm that replacing WP-Cron with real server cron eliminates scheduled post publishing failures on all site traffic levels, making it the essential first step before investigating any other cause of missed WordPress scheduled posts.
Recurring posts — content that should publish on a regular schedule (weekly roundups, monthly newsletters, daily deals) — require a plugin since WordPress’s native scheduling only supports one-time future publishing. The PublishPress Future plugin (formerly Post Expirator) handles both post expiry (automatically un-publishing old content) and recurring scheduling. For truly recurring content generation, combining a scheduling plugin with WordPress REST API automation or a task automation tool (Zapier, Make/Integromat) that creates new draft posts on a schedule provides full recurring content workflow capability. WP Crontrol provides the technical foundation for custom recurring cron events that trigger any PHP callback on any schedule — use it to create custom intervals (bi-weekly, every third Monday) that WordPress’s standard cron scheduling intervals do not include by default, enabling fully custom recurrence patterns for WordPress scheduled posts that require more complex timing than the standard immediate/daily/weekly options.
Monitoring WordPress scheduled posts reliably requires visibility into both the scheduled queue and the publishing confirmation. Install a plugin that sends an email notification when a post publishes — either via an editorial calendar plugin’s notification system or a simple notification plugin configured to email the site admin when post status changes from “scheduled” to “published.” This notification confirms successful publishing within minutes of the scheduled time, rather than discovering a missed post hours later when checking the site manually. For high-volume publishing schedules where multiple posts publish daily, the notification can be a daily digest rather than a per-post email — showing all posts that published in the last 24 hours versus those that were scheduled to publish but remain stuck. This monitoring layer catches WP-Cron regressions (a plugin update that accidentally sets DISABLE_WP_CRON without adding a server cron, for example) before they accumulate into a large backlog of missed content.
The wp-config.php constant ALTERNATE_WP_CRON provides a middle path between the default WP-Cron and full server cron for sites where neither the standard approach nor server cron is available. Setting define('ALTERNATE_WP_CRON', true); changes how WP-Cron is triggered — instead of spawning a non-blocking background request during the page load (which sometimes fails on hosts that restrict loopback connections), it uses a redirect-based approach that is more compatible with restricted hosting environments. This alternate mode does not fix the fundamental traffic-dependency problem of WP-Cron but resolves the specific failure mode where WordPress scheduled posts miss their schedule because the hosting server blocks the loopback HTTP request that standard WP-Cron uses to trigger itself. If neither ALTERNATE_WP_CRON nor server cron resolves the scheduling issue, the hosting provider’s support team can identify the specific server restriction preventing WP-Cron execution.
Staging environment considerations for WordPress scheduled posts: a staging site cloned from production inherits all scheduled posts and the WP-Cron setup. If the staging site is accessible and the server cron runs on both environments, scheduled posts on staging publish automatically — potentially to a publicly accessible staging URL that should not have live content. Disable WP-Cron completely on staging: add define('DISABLE_WP_CRON', true); to the staging wp-config.php without adding a corresponding server cron job. This prevents all WP-Cron tasks from running on staging — no scheduled post publishing, no plugin update checks, no cleanup tasks — keeping the staging environment static for testing without inadvertently publishing content or running background processes that could interfere with the staging environment’s intended use. Related: WordPress Publish Error.






