Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

zhaogood's avatar

How does Laravel scheduled task work on different servers?

We have 3 servers, and I would like to run a command on all servers every ten mimutes without overlapping. We use redis as central cache server.

For example, in Kernel.php file,

protected function schedule(Schedule $schedule)
{
    schedule->command('foo:bar')->everyTenMinutes()->withoutOverlapping();

What I don't understand is in vendor/laravel/framework/src/Illuminate/Console/Scheduling/Event.php file,

    public function mutexName()
    {
        $mutexNameResolver = $this->mutexNameResolver;

        if (! is_null($mutexNameResolver) && is_callable($mutexNameResolver)) {
            return $mutexNameResolver($this);
        }

        return 'framework'.DIRECTORY_SEPARATOR.'schedule-'.sha1($this->expression.$this->command);
    }

This mutexName clearly doesn't use any kind of identifier of the server the command is running on. When use withoutOverlapping(), I think Laravel would only allow the first command that started from one server, and block the other two servers' command from runnning.

In other words, my question is, is it possible to run a command on all servers without overlapping when use a central cache server?

0 likes
12 replies
zhaogood's avatar

@Snapey Sorry I don't get you. The link you provided is for running tasks on one server, but I want to run task on multiple servers.

krisi_gjika's avatar

@zhaogood than don't use a central cache for your scheduler

$schedule->useCache('file');

// your scheduled commands
krisi_gjika's avatar

@zhaogood you will have to test this yourself but try to change the cache driver after those commands

Snapey's avatar

@zhaogood

Sorry I don't get you.

Did you even read the section? Its only like two paragraphs

If your application's scheduler is running on multiple servers, you may limit a scheduled job to only execute on a single server. For instance, assume you have a scheduled task that generates a new report every Friday night. If the task scheduler is running on three worker servers, the scheduled task will run on all three servers and generate the report three times. Not good!

To indicate that the task should run on only one server, use the onOneServer method when defining the scheduled task. The first server to obtain the task will secure an atomic lock on the job to prevent other servers from running the same task at the same time:

Its about ENSURING your job only runs on one server (the first one that can run it)

zhaogood's avatar

@Snapey I don't want to run a command only on one server. I want to run a command on ALL servers and without overlapping.

Snapey's avatar

@zhaogood again your comment demonstrates you did not read the docs

The first server to obtain the task will secure an atomic lock on the job to prevent other servers from running the same task at the same time:

zhaogood's avatar

@Snapey your comment demonstrates you did not read the docs carefully. This is the full paragraph of the sentence you copied from https://laravel.com/docs/10.x/scheduling#running-tasks-on-one-server:

To indicate that the task should run on only one server, use the onOneServer method when defining the scheduled task. The first server to obtain the task will secure an atomic lock on the job to prevent other servers from running the same task at the same time:

I don't know why you didn't read the first sentence. It clearly states this atomic lock is for onOneServer method, which I DON'T use.

I already knew the atomic lock story. Both onOneServer method and withoutOverlapping would create a mutex(atomic lock), but they are different. What I am trying to say is why withoutOverlapping also prevent tasks from different servers. In my opinion withoutOverlapping should only block the overlapping tasks from the same server.

Snapey's avatar

@zhaogood ok, sorry, I did not get the gist of your question and mistook your explanation of what happens as a description of what you want to happen

Short of a PR, you could stagger the schedules by some minutes dependent on something like a server node number.

If your servers were 0,1, & 2 adapt your schedule like


    schedule->command('foo:bar')->hourlyAt($this->atMinutes());

    public function atMinutes()
    {
        $slots = [
            [10,20,30,40,50,0],
            [12,22,32,42,52,2],
            [14,24,34,44,54,4],
        ];

        return $slots[config('app.serverNode')];
    }
zhaogood's avatar

@Snapey thank you. The problem is I need to use withoutOverlapping() so the command doesn't run overlap in each server. I mean we don't really know how long the command will take. It could be seconds, or hours.

Snapey's avatar

@zhaogood how about your own local mutex? let your job start and quit if the mutex is still valid

Please or to participate in this conversation.