⏲️ Estimated reading time: 11 min
Missed scheduled posts lower trust and hurt traffic. This step-by-step guide gives you a tiny, drop-in MU-plugin that creates a real WP-Cron task to catch and publish overdue “future” posts. Learn the installation, testing, server cron setup, troubleshooting, and safety best practices in clear, AdSense-friendly language.
Why Scheduled Posts Miss and How a Tiny MU-Plugin Fixes It
Scheduled publishing should “just work.” Yet many WordPress sites still show “Missed schedule.” That hurts credibility, ad revenue, and newsletter timing. The real problem is reliability. WP-Cron depends on visits or external triggers. On low-traffic or cached sites, events can slip. A simple, safe, and reliable fix exists.
You can add a small code snippet as a must-use plugin. It creates a five-minute recurring WP-Cron task. The task scans for overdue “future” posts and publishes them. It adds a two-minute grace period to avoid racing brand-new schedules. The code triggers normal WordPress hooks. Your SEO, sitemaps, and caches behave as expected.
Below you get a full copy-paste solution, two installation options, and a reliable server cron recipe. You also get testing tips, logs guidance, WooCommerce compatibility notes, multisite behavior, performance safeguards, and best practices for production.
The Drop-In Code (Copy–Paste Safe)
Save the file exactly as described in the installation sections. Keep the header intact so WordPress recognizes it.
<?php
/**
* Plugin Name: Fix Missed Schedule (MU)
* Description: Publishes posts whose schedule time has passed but are still "future".
* Author: TB
* Version: 1.0
*/
if (!defined('ABSPATH')) exit;
/**
* Add a 5-minute cron interval.
*/
add_filter('cron_schedules', function ($schedules) {
if (!isset($schedules['every_five_minutes'])) {
$schedules['every_five_minutes'] = [
'interval' => 5 * 60,
'display' => __('Every 5 Minutes')
];
}
return $schedules;
});
/**
* Schedule the recurring event on load if not already scheduled.
*/
add_action('init', function () {
if (!wp_next_scheduled('tb_fix_missed_schedules_event')) {
wp_schedule_event(time() + 60, 'every_five_minutes', 'tb_fix_missed_schedules_event');
}
});
/**
* Handler: find overdue "future" posts and publish them.
*/
add_action('tb_fix_missed_schedules_event', function () {
// Allow 2-minute grace to avoid racing brand-new schedules
$now_gmt = current_time('timestamp', true) - 120;
$args = [
'post_type' => 'any',
'post_status' => 'future',
'fields' => 'ids',
'date_query' => [
[
'column' => 'post_date_gmt',
'before' => gmdate('Y-m-d H:i:s', $now_gmt),
'inclusive' => true,
],
],
'posts_per_page' => 50,
'orderby' => 'date',
'order' => 'ASC',
'no_found_rows' => true,
'suppress_filters' => true,
];
$overdue = get_posts($args);
if (!$overdue) return;
foreach ($overdue as $post_id) {
// Safety: confirm still "future"
$status = get_post_status($post_id);
if ($status !== 'future') continue;
// Publish (triggers the usual hooks)
wp_publish_post($post_id);
// Optional: mark that we auto-published
update_post_meta($post_id, '_tb_missed_schedule_fixed', gmdate('c'));
}
});
/**
* Clean up on manual deactivation (not typical for MU, but harmless).
*/
register_deactivation_hook(__FILE__, function () {
$timestamp = wp_next_scheduled('tb_fix_missed_schedules_event');
if ($timestamp) wp_unschedule_event($timestamp, 'tb_fix_missed_schedules_event');
});
Option A – Must-Use Plugin (Recommended)
The MU-plugin loads automatically and cannot be deactivated by accident. This makes it perfect for reliability fixes.
Install steps
- Connect via SFTP or File Manager.
- Create the folder:
wp-content/mu-pluginsif missing. - Create a file:
fix-missed-schedule.php. - Paste the code above into the file. Save it.
- Visit your site once to prime WP-Cron. The event schedules within 60 seconds.
- Wait up to five minutes. The task runs and publishes overdue “future” posts.
Why MU is best
- Always active, even after plugin bulk actions.
- Ideal for infrastructure reliability, not features.
- Lightweight and safe for all sites, including multisite.
Option B – Regular Plugin
Prefer a standard plugin that you can activate or deactivate from Plugins? Use this approach.
Install steps
- Create the folder:
wp-content/plugins/fix-missed-schedule/. - Create
fix-missed-schedule.phpinside that folder. - Paste the same code.
- Go to Plugins → Installed Plugins.
- Activate Fix Missed Schedule.
- Visit the site to prime WP-Cron. The event schedules within 60 seconds.
When to choose this
- You need the ability to deactivate from the dashboard.
- You want to bundle this with other operational tools.
- You prefer traditional plugin management.
Make WP-Cron Truly Reliable (Server Cron)
WP-Cron fires on page loads by default. That is unreliable for low-traffic sites. It can also collide with heavy caching layers. The best practice is to disable the default trigger and run a real server cron every five minutes.
Step 1: Disable the built-in trigger
Edit wp-config.php and add:
define('DISABLE_WP_CRON', true);
Step 2: Add a system cron job
Choose one of the following. Both are stable.
PHP direct call
*/5 * * * * /usr/bin/php -q /path/to/your/site/public_html/wp-cron.php >/dev/null 2>&1
WP-CLI call
*/5 * * * * /usr/bin/wp cron event run --due-now --path=/path/to/your/site >/dev/null 2>&1
Notes
- Keep the five-minute cadence to reduce latency.
- Point to the correct PHP and WP-CLI paths.
- On cPanel, use the Cron Jobs interface with the same command.
How the Fix Works Internally
The code registers a custom cron schedule: every five minutes. It schedules a recurring event on init if one is not already present. Every run, it:
- Calculates the current GMT time, minus a two-minute grace period.
- Queries for posts with status
futurewhosepost_date_gmtis earlier than or equal to that moment. - Publishes each matched post using
wp_publish_post(). - Records a meta
_tb_missed_schedule_fixedtimestamp for auditing.
Because it calls wp_publish_post(), all normal publish hooks fire. Your SEO plugins, sitemaps, webhooks, and caches update as usual.
Safety and Performance Considerations
Reliability fixes must remain safe under load. This snippet aims for that.
Query limits
- Limits to 50 posts per pass.
- Uses
no_found_rowsto avoid count overhead. - Requests only IDs for fast processing.
Race avoidance
- Adds a two-minute buffer so very fresh schedules are not double-handled.
- Re-checks
get_post_status()for each ID before publishing.
Hook friendliness
- Uses official APIs.
- Triggers normal hooks for compatibility.
Multisite behavior
- MU-plugins run on every site in the network.
- WP-Cron events schedule per site context.
- If you need network-wide control, use WP-CLI from a server cron.
Step-by-Step Testing Checklist
Do a quick, controlled test. Confirm behavior before relying on it.
- Create a new post.
- Set Status to Scheduled for five minutes in the future.
- Temporarily block visits if you want to simulate low traffic.
- Wait until the scheduled time passes.
- Ensure the new cron runs within five minutes.
- Confirm the post shows Published.
- Check post meta
_tb_missed_schedule_fixedfor a timestamp. - Review your logs or monitoring dashboard for any errors.
Optional fast-forward
Use WP-CLI to manually run due events:
wp cron event run --due-now
This confirms the event triggers as expected.
Troubleshooting “Missed Schedule” After Applying the Fix
Still seeing issues? Work through these points.
WP-Cron never triggers
- Did you add
DISABLE_WP_CRONbut skip server cron? Add the cron job. - Check PHP path in the cron job. Correct it if wrong.
- On shared hosting, watch for execution restrictions.
Caching and firewalls
- Some hosts block
wp-cron.phprequests. - Edge caching can prevent traffic-based cron triggers.
- Server cron fully bypasses that.
Time drift
- Ensure server time and WordPress timezone are configured.
- The code uses GMT for safety, minimizing drift issues.
Plugin conflicts
- Rarely, aggressive “scheduler” plugins modify cron behavior.
- Temporarily disable other cron plugins. Test again.
Database load
- The query is light. However, very large sites should monitor load.
- Reduce
posts_per_pageif needed. Increase frequency instead.
Working with WooCommerce, EDD, and Custom Post Types
This fix targets any post type with status future. That includes WooCommerce products scheduled for sales page reveals or custom post types used for editorial calendars.
Key notes
- It will not publish drafts. It only acts on
futurestatus. - It respects your post type supports and hooks.
- If your CPT uses custom workflows, publish hooks still fire.
Best practice
- Test on staging if you run complex automations on publish.
- Verify integrations like webhooks, JSON feeds, or newsletter triggers.

Logs, Monitoring, and Auditing
You can keep a lightweight audit without complex logging stacks.
Post meta trail
- Each auto-publish stores
_tb_missed_schedule_fixedwith an ISO 8601 timestamp. - Query posts by this meta if you need a report.
Server logs
- Cron outputs are suppressed in examples.
- For debugging, remove
>/dev/null 2>&1in your cron job temporarily. - Review
error_logfor PHP issues.
WP-CLI
wp cron event listshows scheduled tasks.wp cron event run --due-nowtriggers them immediately.
Security and Maintenance Best Practices
Keep infrastructure code boring and safe.
Principles
- Fail fast. Do nothing if nothing is due.
- Avoid direct SQL. Use WordPress APIs for safety.
- Keep the file small and auditable.
- Commit it to version control if possible.
- Document the presence of the MU-plugin for teammates.
Deactivation behavior
- MU-plugins do not appear in the Plugins screen.
- The deactivation hook is harmless here.
- If you convert to a normal plugin, the hook cleans up the scheduled event.
When You Should Absolutely Use a Server Cron
Some environments virtually require a real cron.
Examples
- Low or spiky traffic patterns.
- Full-page caching at the edge or proxy.
- Headless or decoupled frontends.
- High-stakes schedules like newsrooms or campaign launches.
With a server cron, timing stays consistent. Your schedules hit within five minutes under normal load.
Frequently Asked Questions (Text)
How often does the task run?
Every five minutes. You can change the interval by modifying the schedule filter.
Will this publish drafts by mistake?
No. It only targets posts with status future whose scheduled time has already passed.
Does it work on multisite?
Yes. MU-plugins load network-wide. Cron events schedule per site. Test per site if needed.
Is it safe for WooCommerce products or CPTs?
Yes. It uses wp_publish_post(), so standard hooks and behaviors apply.
What if my host blocks WP-Cron?
Disable the built-in trigger and add a server cron job. Use the commands in this guide.
Can I reduce latency to two minutes?
Yes. Lower the interval. Consider every_two_minutes with a custom schedule, but monitor load.
How do I know it worked?
Check the post status and the _tb_missed_schedule_fixed meta timestamp. Also review your cron list.
Will this conflict with other schedule fixer plugins?
Usually not, but avoid running multiple fixers simultaneously. Choose one approach.
Can I log each publish to a file?
Yes. Add a simple error_log() line in the loop. Keep logs short-lived.
Does it affect SEO or sitemaps?
It triggers normal publish hooks, so SEO plugins update sitemaps and metadata as usual.
Practical Deployment Playbook
Follow this exact flow for stable results.
Staging first
Clone production to staging. Install the MU-plugin there. Disable traffic-based WP-Cron. Add a server cron. Schedule a few posts within the next ten minutes. Watch them publish without manual refresh.
Production rollout
Copy the MU-plugin file to mu-plugins. Add the DISABLE_WP_CRON line. Create the server cron job. Verify paths. Schedule two test posts. Confirm publish within five minutes.
Observability
For a week, spot-check scheduled posts. If all good, you can forget it and enjoy reliability.
Extra Tips for Editorial Teams
Small habits boost success.
- Schedule posts at five-minute boundaries for cleaner timing.
- Avoid changing timezones often. Keep WordPress timezone stable.
- Coordinate newsletters and social scheduling on the presumed five-minute window.
- Document the fix in your internal handbook.
Editor-Friendly Summary
- This MU-plugin adds a reliable five-minute check.
- It publishes overdue “future” posts automatically.
- Disable traffic-based WP-Cron.
- Add a server cron for guaranteed runs.
- Test with a few posts.
- Enjoy dependable schedules.
Disclaimer and Source Hygiene
This guide is educational and provided “as is.” Always test on staging before production. Results vary by hosting, traffic, caching, and plugin stack. The code uses official WordPress APIs and avoids direct SQL for safety. Maintain regular backups and monitor logs during rollout.
🔔 For more tutorials like this, consider subscribing to our blog.
📩 Do you have questions or suggestions? Leave a comment or contact us!
🏷️ Tags: WordPress cron, missed schedule, wp-cron, server cron, MU-plugin, scheduled posts, WP-CLI, WordPress reliability, publishing workflow, editorial tools
📢 Hashtags: #WordPress, #WPCron, #MissedSchedule, #Blogging, #ContentStrategy, #MUPlugin, #WPCLI, #DevOps, #WebHosting, #SEOTips
Your Schedule, On Time, Every Time
Reliable schedules are a publishing superpower. This small MU-plugin, paired with a real server cron, gives you consistent timing without heavy dependencies. Install once, test quickly, and let the workflow run. Your audience sees posts on time, your SEO stays aligned, and your team remains confident.