The goal

I want to use wp_schedule_single_event( ) to execute a single event that sends me an e-mail 8 minutes after the user submits a form.

The issue

The following code is in my functions.php:

function nkapi_send_to_system( $args ) {
  wp_mail( 'xxx', 'xxx', $args );

add_action( 'nkapi_send', 'nkapi_send_to_system' );

function schedule_event( $id ) {
  wp_schedule_single_event( current_time( 'timestamp' ) + 480, 'nkapi_send', array( $id ) );

And the following code is used to call schedule-event:

schedule_event( $_SESSION['insert_id'] ); // the $_SESSION var contains an INT

After waiting some more than 8 minutes there wasn't an e-mail in my inbox.

What I tried

With the plugin Core Control it's possible to see wich cron jobs are scheduled.

Core Control screen

After a couple of changes I managed to get them quite correct, and better, when I hit "Run Now", I actually get an e-mail in my inbox.

But why the cron's don't execute when I visit my site after 8 minutes. What possibly is wrong with this code? I have to say that this is my first time using WP Cron.

I tried more

After the comment of vancoder id decided to test if the code works if I put the following code directly in the functions.php:

function schedule_event( $id ) {
  wp_schedule_single_event( time(), 'nkapi_send', array( $id ) );

if ( isset( $_SESSION['insert_id'] ) ) {
  if ( ! array_key_exists( 'insert_scheduled', $_SESSION ) || $_SESSION['insert_scheduled'] != $_SESSION['insert_id'] ) {
    schedule_event( $_SESSION['insert_id'] );
    $_SESSION['insert_scheduled'] = $_SESSION['insert_id'];

The downside of this code is, the user has to go to another page before this code is executed. But on the other side, this doesn't work either so that wouldn't be my first issue...

  • 1
    Where and how is schedule_event( $_SESSION['insert_id'] ); fired?
    – vancoder
    Commented Mar 27, 2013 at 16:23
  • A shortcode includes a separate file (with a form in it) in a page, when that form is posted the page reloads, the same file then executes the schedule_event( ), lets say in top of the included file loaded by the shortcode. Commented Mar 28, 2013 at 7:48
  • Do any crons work? wp_version_check etc?
    – vancoder
    Commented Mar 28, 2013 at 17:28
  • I didn't get any crons to work. What could be the problem of that? Commented Mar 29, 2013 at 8:09
  • To confirm - even core cron jobs fail?
    – vancoder
    Commented Apr 4, 2013 at 16:44

6 Answers 6


First can you please confirm that you don't have any caching plugins enabled? Caching plugins can interfere with cron jobs because your visitors are not served a live page but a cached version of your page.

If you have a caching plugin enabled, you can choose one of your pages, add an exclussion to your caching plugin's settings for that page so that it is never cached.

Then you'll have to manually create a cron job (using cpanel if you're on a shared hosting environment or from the terminal if it's a VPS/dedicated server) that will visit that page every few minutes.

I hope that helps!

  • I have a caching plugin enabled! W3 Total Cache to be precise Commented Apr 9, 2013 at 13:04
  • There are options to disable all cache, but I don't see an option to enable/disable cache for plugins only Commented Nov 2, 2020 at 19:53

Firstly, define your custom cron job schedules.

add_filter('cron_schedules', array($this, 'cron_schedules'));

public function cron_schedules($schedules){
    $prefix = 'cron_';// Avoid conflict with other crons. Example Reference: cron_30_mins
    $schedule_options = array(
        '30_mins' => array(
            'display' => '30 Minutes',
            'interval' => '1800'
        '1_hours' => array(
            'display' => 'Hour',
            'interval' => '3600'
        '2_hours' => array(
            'display' => '2 Hours',
            'interval' => '7200'
    /* Add each custom schedule into the cron job system. */
    foreach($schedule_options as $schedule_key => $schedule){
        $schedules[$prefix.$schedule_key] = array(
            'interval' => $schedule['interval'],
            'display' => __('Every '.$schedule['display'])
     return $schedules;

You need to decide where and when to actually schedule the event.

Here is just an example snippet of code, which makes a call to a custom class method:

$schedule = $this->schedule_task(array(
    'timestamp' => current_time('timestamp'), // Determine when to schedule the task.
    'recurrence' => 'cron_30_mins',// Pick one of the schedules set earlier.
    'hook' => 'custom_imap_import'// Set the name of your cron task.

Here is the code which actually schedules the event:

private function schedule_task($task){
    /* Must have task information. */
        return false;
    /* Set list of required task keys. */
    $required_keys = array(
    /* Verify the necessary task information exists. */
    $missing_keys = array();
    foreach($required_keys as $key){
        if(!array_key_exists($key, $task)){
            $missing_keys[] = $key;
    /* Check for missing keys. */
        return false;
    /* Task must not already be scheduled. */
    /* Schedule the task to run. */
    wp_schedule_event($task['timestamp'], $task['recurrence'], $task['hook']);
    return true;

Now, all you need to do is make a call to the name of your custom cron task. In this example the cron task name is custom_imap_import.

add_action('custom_imap_import', array($this, 'do_imap_import'));

public function do_imap_import(){
    // .... Do stuff when cron is fired ....

So in this example, $this->do_imap_import(); is called every 30 minutes (assuming you have enough traffic to your website).


Requires a page visit in order for your cron to fire at correct times.

Example: If you scheduled a task at 30 minute intervals, but no one visits your site for 4 hours, your cron job won't be fired until that visitor comes to your site 4 hours later. If you really truly need your task fired every 30 minutes, then it is advised to setup a legitimate cron job via your web hosting provider to visit your website at the desired intervals.

WordPress cron jobs don't make your website slow!

Maybe you are thinking what if the cron-script takes a long time to be executed, will the visitors have to wait until the script is executed. Nope! How can that be possible? If you look at the wp-cron.php file you will find a line


It's a php.ini configuration that sets that if you stop loading the site/script the script won't stop executing.

If you look at the wp-includes/cron.php file you'll find a line like this:

wp_remote_post( $cron_url, 
array('timeout' => 0.01,
 'blocking' => false, 
 'sslverify' => apply_filters('https_local_ssl_verify', true)) );

That means WordPress will wait only 0.01 second for triggering the execution then it will abort but as you have set ignore_user_abort to true the script will be executing. This functionality is a huge advantage to execute large scripts in WordPress cron jobs.

Functions available for aid:

  • 9
    This is a remarkably comprehensive response, which as far as I can see, fails to address the actual question - which is why do all scheduled tasks (including core tasks) fail.
    – vancoder
    Commented Apr 4, 2013 at 16:40
  • This answer is to guide the user in the right direction for understanding and scheduling WordPress cron tasks correctly. Commented Apr 4, 2013 at 17:07
  • 4
    This sure helped me a lot understanding cron schedules with WordPress Commented Apr 9, 2013 at 13:08
  • 2
    Michael, you should answer more often. Great one +1
    – kaiser
    Commented Oct 3, 2013 at 2:36
  • 1
    I think WP_Cron uses GMT under the hood, like the rest of WP, so it'd be better to schedule the first event at time() instead of current_time().
    – Ian Dunn
    Commented Nov 25, 2014 at 1:09

WordPress Cron allows you to schedule tasks, but they will only execute if there is a request made to the site. For each request that WordPress receives it will check to see if there are cron jobs to process, and if so fires off a request to /wp-cron.php?doing_wp_cron asynchronously to process the job. If a job's scheduled start passes without a request, then the cron process won't be started.

Since you are able to see and run your scheduled jobs, it's possible that there are no requests that trigger the cron job to start, especially if you're using a caching plugin. The best option for offloading this to a more regular schedule is to disable the default check in WordPress and use crontab.

First to disable the default check (which can help a bit with client side performance), add the following to wp-config.php:

// Disable default check for WordPress cron jobs on page loads
define( 'DISABLE_WP_CRON', true );

Next you create a task to fetch the wp-cron.php page once a minute to process any jobs on the back end, from the command line enter crontab -e and then add a line that looks like the following:

*/1 * * * * /usr/bin/curl --silent http://example.com/wp-cron.php?doing_wp_cron=$(date +\%s.\%N) >/dev/null 
  • 2
    If you don't give doing_wp_cron a value, this is highly likely to cause jobs to sometimes be executed twice. Use doing_wp_cron=$(date +\%s.\%N) to prevent that. Commented Nov 10, 2013 at 11:04

For anyone protecting their (development) site from public access, HTTP Authentication can be the cause of WP Cron not functioning.

In case it can help anyone, here is my list of things I did before identifying and understanding the requirements of WP Cron:

  • I noticed events were correctly scheduled and could be run using WP-CLI.
  • And also noticed that accessing /wp-cron.php?doing_wp_cron through the browser did trigger executions, as suggested in e.g. 13625.
  • The official documentation was read.
  • I ensured DISABLE_WP_CRON was not set.
  • And learnt that ALTERNATE_WP_CRON was a successful, yet unsatisfying, workaround.
  • To rule out regression bugs, I tried installing a couple of older wordpress releases.
  • All plugins were disabled and theme switched to the default one, to isolate the issue.
  • People mentioned the term loopbacks, but lacking related errors or warnings I considered it irrelevant.
  • Finally, a question with an answer actually explaining how to debug cron was found.
  • Once attaching Xdebug to wp_cron() I could indeed see that execution ended up in wp_remote_post(), which clearly failed.

When knowing what to search for, I found this great article on causes for WP Cron issues by Jeff Starr. At the end of it, he links to his wp-cron-http-auth plugin.


Check that DISABLE_WP_CRON is not set in your config.

Failing that, try disabling all plugins (except core control - though I would use wp-crontrol) and see if your core jobs work. If they do, you are experiencing plugin interference somewhere.

Similarly, try switching to a standard twentysomething theme.

If none of these make any difference, chances are it's a hosting issue.

  • I don't have DISABLE_WP_CRON set in my wp-config.php, I'll try more things and come back later Commented Apr 9, 2013 at 13:07

Check any plugin that hides Wordpress.

How to see if this is the problem?

  1. Navigate to http(s)://yoursite.com/wp-cron.php You should see an empty page. A completely empty one.
  2. Besides you must see in a cron job manager a time under "Next execution": Cron job scheduled - if wp-cron.php works properly (not only the text "In queue" - but a given time - for some entries "In queue" is OK sometimes, but if it is the only thing you see -> your cron does not work.)

+1. Do not believe any plugins that "check if cron is working" - e.g. WP Cron status checker plugin has shown that cron is working. But in fact it did not. Whatever it shows - believe your eyes and not this plugin!

Conclusion: If it is 404 error - then switch off a) not only caching plugins as others suggest b) but also any plugins that hide Wordpress.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.