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

Sergiu17's avatar

Laravel job chains

Hello folks,

I need some help, I have a chain that consists of 5 jobs, usually takes ~20 seconds to execute all of them and they are executed in the right order as expected while there's only one chain dispatched!

Now, when I dispatch two chains, then the jobs get mixed up, but still jobs inside the chain are executed in proper order..

Now the problem is when I dispatch hundreds of chains, and in this case I may wait for hours to finish the first chain..is there any way to order these chains? to execute them one after the other?

Bus::chain([
    new JobA($task),
    new JobB($task),
    new JobC($task),
    new JobD($task),
    new JobE($task),
])->dispatch();

I tested this with a single worker and with multiple workers, same thing..

0 likes
7 replies
Braunson's avatar

Executing jobs in Laravel via the queue is an asynchronous operation - generally once jobs are pushed onto the queue, their order of execution depends on how they're popped from the queue by the queue workers. This means that Laravel doesn't guarantee a specific order of execution when concurrently processing multiple job chains.

However, if the order of these chains is important, they should ideally be combined into a single chain. Jobs in a chain are executed in the order they are listed, and if one job fails, the rest of the chain will not be executed.

Here is an example:

Bus::chain([
  new JobA(),
  new JobB(),
  new JobC(),
  // add more Jobs here
])->dispatch();

In this chain, JobB would not be started until JobA has completed successfully, and JobC won't start until JobB completes successfully.

If you have multiple chains and need to ensure one chain is finished before starting another, you could dispatch the next chain in the final job of the previous chain.

class FinalJobOfFirstChain implements ShouldQueue
{
    // ...
    public function handle()
    {
        // ... do job's work

        // Dispatch next chain.
        Bus::chain([
            new Job1OfSecondChain(),
            new Job2OfSecondChain()
        ])->dispatch();
    }
}

This way, the second Bus chain won't start until the first chain is finished, because the first job of the second chain is being dispatched from the final job of the first chain.

Remember: If a particular order of job execution is critical, consider whether these jobs are good candidates for queueing. Critical ordering requirements and asynchronous processing are sometimes at odds with each other.

1 like
Sergiu17's avatar

@Braunson I get your example but I'm not sure if I can implement it, every job depends on a $task ( it's just an example )

public function store(Request $request)
{
    $task = Task::create($request->validated());

    Bus::chain([
        new JobA($task),
        new JobB($task),
        new JobC($task),
        new JobD($task),
        new JobE($task),
    ])->dispatch();

    return response();
}

// and it's too much work in every class, in order to merge them into a single class, but it will easily fix the problem ( I'll consider merging all the classes into one, then dispatch a single job instead of a chain )

I'm not sure if I'll be able to dispatch somehow the next chain in JobE class

Regarding if a particular order of job execution is critical or not, it's not critical, the main problem is when I dispatch hundreds of chains, in this case I have to wait for hours for the first chain to complete. When I have few chain, not an issue at all, I don't care which one finishes first.

Another stupid idea I have is to dispatch the chains on database connection, then add another worker that will move jobs from database to redis in chunks of 5, then eventually the worker will process 5 jobs simultaneously

Braunson's avatar

@Sergiu17 You are using workers and queued jobs right? Your not using sync?

If so how many jobs are in your first chain that it's taking hours to work through? If not many, I'd probably look into why it's taking hours and see if you can optimize the queries/code..

Sergiu17's avatar

@Braunson Yes, I'm using workers and queued jobs

You will also learn something new today)) I'll try to explain chains flow, let's assume database driver

- chain of 5 jobs is dispatched
- a single record is stored into database that contains 5 jobs, 
-> loop
- worker takes the record, processes first job from the chain
- creates a new record into the database that contains 4 jobs
- deletes the record that has 5 jobs
-> end loop

for the better understanding add to your AppServiceProvider some logs and try on your own

DB::listen(function ($query) {
    Log::info('query', [$query->sql, $query->bindings]);
});
Zoeypenelope's avatar

Thankfully, Laravel allows you to easily create queued jobs that may be processed in the background. By moving time intensive tasks to a queue, your application ...A specific feature of chaining is that the next job in the chain is only run if the previous job does not fail. That's not a disadvantage; that ...In Laravel, a queue is a feature that allows you to defer time-consuming tasks, such as sending emails, processing data, or interacting with external services, to be executed in the background rather than blocking the main execution flow of your application.According to Laravel doc, Laravel's job batching feature allows you to easily execute a batch of jobs and then perform some action when the batch of jobs has completed executing

Sergiu17's avatar

@amitsolanki24_ Thank you, but it's not about the priority, every chain has the same priority, also, I dispatch on a separate queue ->onQueue() and I have a worker that processes jobs from this queue only

1 like

Please or to participate in this conversation.