Series: WordPress Performance on DirectAdmin (Rocky Linux 9)
Phase 4: Cron, Automation & Background Tasks — Part 15 of 30
Scheduled Posts Not Publishing? WP-Cron Timing Explained
Introduction
WordPress scheduled posts rely on WP-Cron, a pseudo-cron system that can be unreliable under certain hosting setups. Sysadmins managing WordPress on DirectAdmin (Rocky Linux 9) often encounter issues where scheduled posts are not published at the expected time. This article explains why, and provides practical, reproducible steps to ensure reliable cron execution within the context of DirectAdmin-managed servers.
Understanding WP-Cron and Its Limitations
WP-Cron is not a true system cron. By default, it runs on every page load if there are scheduled tasks (e.g., future posts) waiting. This means if your site receives low or irregular traffic, scheduled posts may not publish on time, or at all. High-traffic sites can trigger WP-Cron too frequently, leading to performance issues.
DirectAdmin setups on Rocky Linux 9 typically use PHP-FPM with either NGINX or Apache (or both) as the web server. The DirectAdmin panel manages PHP-FPM pools and server configs per domain. This impacts how WP-Cron and background tasks are executed, especially with restrictive PHP-FPM settings, HTTP authentication, or custom web server templates.
Diagnosing WP-Cron Issues on DirectAdmin (Rocky Linux 9)
Checklist: Confirming the Problem
- Are scheduled posts stuck in “missed schedule” state?
- Is your site behind HTTP auth or maintenance mode?
- Are there PHP errors or timeouts in
/var/log/php-fpm/www-error.logor per-user logs? - Is traffic volume low (few page loads to trigger cron)?
- Are there any relevant messages in
/var/www/html/wp-content/debug.log(ifWP_DEBUG_LOGis enabled)?
Step-by-Step: Testing WP-Cron Execution
-
Check scheduled events:
cd /home/USERNAME/domains/DOMAIN/public_html sudo -u USERNAME wp cron event list --path=$(pwd)If scheduled posts are listed as overdue, WP-Cron is not running correctly.
-
Run WP-Cron manually:
sudo -u USERNAME wp cron event run --due-now --path=$(pwd)Verify if scheduled posts are published after manual execution.
-
Test WP-Cron HTTP endpoint:
curl -I https://DOMAIN/wp-cron.php?doing_wp_cronLook for
HTTP/2 200and no authentication prompts. -
Check PHP-FPM logs for errors:
sudo tail -n 50 /var/log/php-fpm/www-error.logAlso check per-user logs in
/home/USERNAME/.php/php-fpm.logif present.
DirectAdmin, PHP-FPM, and Cron: Key Considerations
On DirectAdmin-managed servers, each domain often runs under its own PHP-FPM pool. Resource limits, max_children, or process timeouts can interfere with cron execution, especially if background tasks are heavy or blocked by insufficient RAM/CPU allocations.
Additionally, DirectAdmin’s NGINX/Apache templates may restrict access to wp-cron.php (e.g., via .htaccess or NGINX rules), or enable HTTP authentication which breaks automated requests.
Checklist: Server and Panel Settings
- Ensure
wp-cron.phpis not blocked by authentication or deny rules. - Check PHP-FPM pool settings for the affected user/domain:
/usr/local/directadmin/data/users/USERNAME/php-fpmXX.conf- Parameters:
pm.max_children,request_terminate_timeout,memory_limit
- Review server logs for OOM or process killing activity.
Disabling WP-Cron and Using System Cron (Recommended)
For reliability, it is best practice to disable the default WP-Cron trigger and instead invoke it via system cron (crontab). This is especially important for sites with low or unpredictable traffic.
Warning: Making mistakes in wp-config.php or crontab can cause downtime. Ensure you have working backups and test changes on a staging environment first.
Step 1: Disable Internal WP-Cron Trigger
Edit wp-config.php in the site’s document root:
sudo -u USERNAME vi /home/USERNAME/domains/DOMAIN/public_html/wp-config.php
Add before the line /* That's all, stop editing! */:
define('DISABLE_WP_CRON', true);
Step 2: Add a System Cron Job
Set up a cron job as the site’s user (not root) to trigger WP-Cron reliably:
sudo crontab -u USERNAME -e
Add the following line (run every 5 minutes, adjust as needed):
*/5 * * * * /usr/bin/php -q /home/USERNAME/domains/DOMAIN/public_html/wp-cron.php > /dev/null 2>&1
For multisite or high-traffic installs, consider reducing frequency (e.g., every 1 minute), but monitor resource usage.
Alternative: Use WP-CLI for Cron
WP-CLI is more robust and provides better logging. Example cron entry:
*/5 * * * * cd /home/USERNAME/domains/DOMAIN/public_html && /usr/local/bin/wp cron event run --due-now --quiet
Test by running manually and checking post status.
Testing and Monitoring WP-Cron Reliability
Step-by-Step: Validation
-
Schedule a test post in the future:
sudo -u USERNAME wp post create --post_title="Scheduled Test" --post_status=future --post_date="YYYY-MM-DD HH:MM:SS" --post_type=post --path=/home/USERNAME/domains/DOMAIN/public_html -
Monitor publication:
- Check the post status with WP-CLI, or in wp-admin.
- Tail error logs during the scheduled time:
sudo tail -f /var/log/php-fpm/www-error.log -
Stress-test with HTTP tools:
- Use
wrkork6to simulate traffic and ensure cron is not being invoked on every request once system cron is active. - Example (
wrk):
wrk -t4 -c40 -d30s https://DOMAIN/ - Use
DirectAdmin Templates and Cron: What to Watch Out For
-
If you use custom NGINX/Apache templates via DirectAdmin:
- Ensure
wp-cron.phpis accessible from localhost and CLI. - Review template includes in
/usr/local/directadmin/data/templates/. - Regenerate configs after template changes with:
sudo /usr/local/directadmin/custombuild/build rewrite_confsWarning: Incorrect template edits can cause downtime across all sites on the server. Edit with caution and test on non-production first.
- Ensure
Good Default Values and Tuning Guidance
- System cron every 5 minutes (
*/5 * * * *) is a good starting point for most blogs and business sites. - Increase frequency for WooCommerce or high-transaction sites (test for load impact).
- Review PHP-FPM pool settings:
pm.max_children=8(small sites),16-32(busy sites)request_terminate_timeout=120memory_limit=256M(raise if running background jobs/plugins)
- Monitor with
sudo journalctl -u php-fpmandsudo tail -f /var/log/php-fpm/www-error.log
Troubleshooting: Common Causes of Failed Scheduled Posts
- Authentication on
wp-cron.php(via .htaccess, NGINX auth, Cloudflare, or WAF) - PHP-FPM process limits too low
- Site traffic too low to trigger default WP-Cron
- Misconfigured cron syntax (wrong user, wrong path, missing PHP binary)
- Plugin conflicts or fatal errors (check
wp-content/debug.log)
Conclusion
Reliable WordPress scheduling depends on understanding how WP-Cron behaves under DirectAdmin on Rocky Linux 9. By disabling the built-in WP-Cron trigger, using system cron, and tuning both PHP-FPM and server configs, sysadmins can ensure posts publish on schedule. Always validate changes in a safe environment and monitor results before deploying to production.
Note: This article offers general technical guidance. Validate all configurations in a safe environment before applying them to production.
Previous: How to Safely Run WordPress Cron Jobs via WP-CLI
Next: How to Monitor and Debug Long-Running WordPress Cron Jobs

