Task schedulers are important and complicated. The Cron utility for Unix-like systems is one of the oldest, most mature, and best out there - but it can be very system specific which doesn't lend itself well to a software package like Wordpress that aims to be ubiquitous.
There are many operations within Wordpress that need to be executed periodically or are long running however, so Wordpress created its own pseudo-cron system in software called WP-Cron. The goal being a platform agnostic way to fire off background tasks on a schedule. While it succeeded in that goal in my opinion, mistaking it for a full blown system level cron can leave developers confused and angry.
There are two main differences between WP-Cron and a regular cron that cause most of the trouble:
- WP-Cron is imprecise in its execution time
- WP-Cron executes as an HTTP request
1) With a system level cron, the application is running as a daemon process, meaning that it is running continuously and always waiting to leap into action. You can schedule events to occur down to a single minute of any day and it will be fired off at exactly that moment by the daemon. With WP-Cron, the process is executed with every Wordpress page request, at which point any jobs which need to be executed will be triggered. If you don't get any visitors for a day however, all of your jobs will be sitting in wait until a visitor arrives to trigger them. On the flip side, if you get a ton of traffic, it's possible that a pile of WP-Cron processes will be spawned in parallel and eat up your system resources if you have some long running tasks.
2) With a system level cron, tasks are executed in the background as a process triggered by the daemon.The process can run as long as necessary to complete its work and duplicate processes will generally not be spawned. With WP-Cron, the tasks are run by making an HTTP request to the site's wp-cron.php file for each visitor, checking for any outstanding tasks, and processing them. Wordpress is smart enough to lock the cron process so additional requests don't execute the same task repeatedly, but due to the flexibility of Wordpress, plugins can still inject cron tasks that get executed on every request which can cause a whole bunch of PHP processes to spawn and consume piles of RAM. Add to this the fact that these jobs are running as an HTTP request which are subject to the server's HTTP execution time limits which by default are usually pretty low, like 30 seconds, so jobs can be aborted abruptly. WP-Cron will also require a resolvable hostname to run since it will be making a request to your sites wp-cron.php file via a URL. This is a problem during development for many.
Keeping those two distinctions in mind, responsible developers will use the WP-Cron only for light tasks which are quick to return and will add extra measures to ensure critical tasks are run when necessary.
Tips and Alternatives
If you have more strict time based requirements that you can't leave up to chance (e.g. a visitor arriving at your site), you need to improve the accuracy of your cron. You can do this in two ways:
- Use a free up-time monitoring program (like uptime robot or similar) to hit your site at http://yoursite.com/wp-cron.php at regular intervals
- Use your systems built in cron system to hit your wp-cron.php file
As I mentioned above, you can avoid many of the performance problems by keeping your scheduled tasks light, but that's not always possible. An alternative for busy sites is to disable WP-Cron and schedule the tasks yourself.
To disable WP-Cron, add the following to your wp-config.php file:
Now schedule your own system level cron to make a direct PHP call to the sites wp-cron.php file at whatever interval makes sense for you:
*/5 * * * * php /var/www/vhosts/mysite/web/wp-cron.php
You could also do this via a wget or curl command if you like.
Going this route - disable WP-Cron and using system cron - gives you much better control, better performance, and greater accuracy. On the flip side, you need to have access to the crontab which your hosting package may not provide. You also need to know your way around the command line.
Sticking with the built in WP-Cron is still a fine option if you're not experiencing load problems, you just need to keep the distinctions in mind and be careful with the type of tasks you schedule.