Are WordPress Heartbeat API ‘beats’ staggered or do they occur simultaneously for all users?

The WordPress Heartbeat API uses admin-ajax.php to run AJAX calls. If User X leaves their browser open, many calls will be made to the server, with each call happening when there is a ‘beat’. Now if User Y leaves their browser open, many more calls will be made to the server, with each of these calls happening when there is a ‘beat’. It’s possible a large website will also have User A, User B and User C all do the same.

My question:

Considering lots of users might access a website simultaneously, are WordPress Heartbeat API ‘beats’ staggered (the ‘beat’ for User X happens a few seconds before the ‘beat’ for User Y) or does a ‘beat’ occur at exactly the same time for all users?

If ‘beats’ aren’t staggered, my concern is a very heavy load on the server at the point when a ‘beat’ occurs.

1

I would think the beats are Staggered by nature, becasue the next tick is determined by the browser time time() within the scheduleNextTick() method in the /wp-includes/js/heartbeat.jsfile:

 var delta = time() - settings.lastTick,
     interval = settings.mainInterval;

where it’s used to schedule the next tick with the setTimeout function:

if ( delta < interval ) {
    settings.beatTimer = window.setTimeout(
        function() {
            connect();
        },
        interval - delta
     );
} else {
    connect();
}

The browser time is defined as:

function time() {
   return (new Date()).getTime();
}

The connect() method contains the ajax call and uses always()

.always( function() {
    settings.connecting = false;
    scheduleNextTick();
})

to schedule the next tick.

The available tick intervals are 5s, 15s, 30s and 60s.

For a large number of very active users, with a short tick interval, the beats might seem to happen simultaneously.

It’s always good to have some data, so you could log the ticks from the logged in users, with the heartbeat_tick hook:

add_action( 'heartbeat_tick', 
    function(  $response, $screen_id  )
    {
        $file =  WP_CONTENT_DIR . '/ticks.log'; // Edit this filepath to your needs.

        if( file_exists( $file ) && is_writeable( $file ) ) 
        {
            file_put_contents( 
                $file, 
                sprintf( "%s - Tick from user_id : %d - from screen_id : %s" . PHP_EOL,
                    date( 'c' ),
                    get_current_user_id(),
                    $screen_id
                ), 
                FILE_APPEND | LOCK_EX 
            );
        }
    }
, 11, 2 ); 

Here’s an example from the ticks.log file:

2014-09-01T12:41:04+00:00 - Tick from user_id : 1 - from screen_id : edit-post
2014-09-01T12:41:19+00:00 - Tick from user_id : 1 - from screen_id : edit-post
2014-09-01T12:41:34+00:00 - Tick from user_id : 1 - from screen_id : edit-post
2014-09-01T12:41:56+00:00 - Tick from user_id : 1 - from screen_id : post
2014-09-01T12:42:11+00:00 - Tick from user_id : 1 - from screen_id : post
2014-09-01T12:42:20+00:00 - Tick from user_id : 3 - from screen_id : upload
2014-09-01T12:42:38+00:00 - Tick from user_id : 1 - from screen_id : post
2014-09-01T12:43:05+00:00 - Tick from user_id : 1 - from screen_id : post
2014-09-01T12:43:08+00:00 - Tick from user_id : 3 - from screen_id : attachment
2014-09-01T12:43:20+00:00 - Tick from user_id : 1 - from screen_id : post
2014-09-01T12:43:36+00:00 - Tick from user_id : 1 - from screen_id : post
2014-09-01T12:44:17+00:00 - Tick from user_id : 3 - from screen_id : profile

Leave a Comment