Bird
Raised Fist0
Laravelframework~5 mins

Job chaining and batching in Laravel

Choose your learning style10 modes available

Start learning this pattern below

Jump into concepts and practice - no test required

or
Recommended
Test this pattern10 questions across easy, medium, and hard to know if this pattern is strong
Introduction

Job chaining and batching help you run tasks in order or as a group. This makes sure tasks happen one after another or all together.

You want to send emails one after another, not all at once.
You need to process images step-by-step, like resize then watermark.
You want to run many tasks and know when all finish.
You want to handle errors if one task in a chain fails.
You want to group jobs and track their progress as a batch.
Syntax
Laravel
<?php

use Illuminate\Bus\Batch;
use Illuminate\Bus\PendingBatch;
use Illuminate\Support\Facades\Bus;

// Job chaining example
Bus::chain([
    new FirstJob,
    new SecondJob,
    new ThirdJob,
])->dispatch();

// Job batching example
Bus::batch([
    new JobOne,
    new JobTwo,
    new JobThree,
])->then(function (Batch $batch) {
    // All jobs completed successfully
})->catch(function (Batch $batch, Throwable $e) {
    // Handle failure
})->dispatch();

Use Bus::chain() to run jobs one after another.

Use Bus::batch() to run jobs together and track them.

Examples
This runs SendWelcomeEmail first, then UpdateUserStats, then LogUserActivity.
Laravel
<?php

// Chain with three jobs
Bus::chain([
    new SendWelcomeEmail,
    new UpdateUserStats,
    new LogUserActivity,
])->dispatch();
This runs GenerateReport and SendReportEmail together and calls the then callback when all finish.
Laravel
<?php

// Batch with jobs
Bus::batch([
    new GenerateReport,
    new SendReportEmail,
])->then(function (Batch $batch) {
    // All jobs done
})->dispatch();
Even with one job, chaining works and runs that job.
Laravel
<?php

// Chain with one job
Bus::chain([
    new SingleJob,
])->dispatch();
Batch with no jobs runs immediately and finishes.
Laravel
<?php

// Batch with no jobs
Bus::batch([])->dispatch();
Sample Program

This example shows three jobs defined with simple handle methods that print messages. It dispatches them as a chain, so they run one after another. Then it dispatches the same jobs as a batch, which runs them together and prints a message when all finish.

Note: To see the output, you must run Laravel's queue worker (e.g., php artisan queue:work).

Laravel
<?php

namespace App\Jobs;

use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;

class FirstJob implements ShouldQueue
{
    use InteractsWithQueue, Queueable, SerializesModels;

    public function handle()
    {
        echo "First job done\n";
    }
}

class SecondJob implements ShouldQueue
{
    use InteractsWithQueue, Queueable, SerializesModels;

    public function handle()
    {
        echo "Second job done\n";
    }
}

class ThirdJob implements ShouldQueue
{
    use InteractsWithQueue, Queueable, SerializesModels;

    public function handle()
    {
        echo "Third job done\n";
    }
}

use Illuminate\Support\Facades\Bus;
use Illuminate\Bus\Batch;
use Throwable;
use App\Jobs\FirstJob;
use App\Jobs\SecondJob;
use App\Jobs\ThirdJob;

// Dispatch chained jobs
echo "Dispatching chained jobs...\n";
Bus::chain([
    new FirstJob,
    new SecondJob,
    new ThirdJob,
])->dispatch();

// Dispatch batch jobs
$batch = Bus::batch([
    new FirstJob,
    new SecondJob,
    new ThirdJob,
])->then(function (Batch $batch) {
    echo "Batch completed successfully\n";
})->catch(function (Batch $batch, Throwable $e) {
    echo "Batch failed: " . $e->getMessage() . "\n";
})->dispatch();

// Output will appear as jobs run in queue worker
OutputSuccess
Important Notes

Job chaining runs jobs one by one, waiting for each to finish before starting the next.

Job batching runs jobs in parallel and lets you track when all finish or if any fail.

Common mistake: forgetting to run the queue worker, so jobs never execute.

Use chaining when order matters. Use batching when you want to run many jobs and track them.

Summary

Job chaining runs tasks in a set order, one after another.

Job batching runs many tasks together and tracks their progress.

Both help manage background work easily and reliably in Laravel.

Practice

(1/5)
1. What is the main difference between job chaining and job batching in Laravel?
easy
A. Job chaining is for database tasks only; job batching is for email tasks only.
B. Job chaining runs jobs in parallel; job batching runs jobs sequentially.
C. Job chaining runs jobs one after another; job batching runs jobs together and tracks progress.
D. Job chaining requires manual tracking; job batching does not track progress.

Solution

  1. Step 1: Understand job chaining

    Job chaining runs jobs one after another in a specific order.
  2. Step 2: Understand job batching

    Job batching runs many jobs together and tracks their progress as a group.
  3. Final Answer:

    Job chaining runs jobs one after another; job batching runs jobs together and tracks progress. -> Option C
  4. Quick Check:

    Job chaining = sequential, Job batching = grouped with progress [OK]
Hint: Chaining = sequence; batching = group with progress tracking [OK]
Common Mistakes:
  • Confusing parallel and sequential execution
  • Thinking batching runs jobs one by one
  • Assuming chaining tracks progress automatically
2. Which of the following is the correct syntax to chain two jobs JobA and JobB in Laravel?
easy
A. JobA::chain([new JobB])->dispatch();
B. JobA::dispatch()->chain([JobB]);
C. dispatch(new JobA)->chain(new JobB);
D. dispatch(new JobA)->chain([new JobB]);

Solution

  1. Step 1: Recall chaining syntax

    In Laravel, chaining jobs uses dispatch(new JobA)->chain([new JobB]).
  2. Step 2: Check options for correct method calls

    dispatch(new JobA)->chain([new JobB]); matches the correct syntax with dispatch(new JobA)->chain([new JobB]);.
  3. Final Answer:

    dispatch(new JobA)->chain([new JobB]); -> Option D
  4. Quick Check:

    dispatch + chain array = correct chaining syntax [OK]
Hint: Use dispatch(new Job)->chain([jobs]) for chaining [OK]
Common Mistakes:
  • Calling chain() on the job class instead of dispatch
  • Passing a single job without array to chain()
  • Using incorrect method order
3. Given the following code, what will be the output in the logs if all jobs succeed?
Bus::batch([
    new Job1(),
    new Job2(),
    new Job3()
])->then(function () {
    Log::info('Batch completed successfully');
})->dispatch();
medium
A. Logs 'Batch completed successfully' immediately after dispatch.
B. Logs 'Batch completed successfully' after all jobs finish.
C. No logs will be created because then() is not supported.
D. Logs 'Batch failed' if any job fails.

Solution

  1. Step 1: Understand batch then() callback

    The then() callback runs after all jobs in the batch succeed.
  2. Step 2: Analyze the code behavior

    Since all jobs succeed, the callback logs 'Batch completed successfully' after finishing.
  3. Final Answer:

    Logs 'Batch completed successfully' after all jobs finish. -> Option B
  4. Quick Check:

    Batch then() runs after success [OK]
Hint: then() runs after all batch jobs succeed [OK]
Common Mistakes:
  • Thinking then() runs immediately after dispatch
  • Assuming then() runs on failure
  • Believing no logs are created
4. Identify the error in this job chaining code:
dispatch(new JobA)->chain(new JobB);
medium
A. chain() expects an array of jobs, not a single job instance.
B. dispatch() cannot be used with chaining.
C. JobB must be dispatched separately before chaining.
D. JobA must be a queued job class, not a job instance.

Solution

  1. Step 1: Check chain() parameter requirements

    The chain() method requires an array of job instances.
  2. Step 2: Analyze the code

    The code passes a single job instance new JobB without wrapping it in an array.
  3. Final Answer:

    chain() expects an array of jobs, not a single job instance. -> Option A
  4. Quick Check:

    chain() needs array of jobs [OK]
Hint: Always pass an array to chain(), even for one job [OK]
Common Mistakes:
  • Passing a single job without array to chain()
  • Trying to dispatch chained jobs separately
  • Confusing dispatch and chain usage
5. You want to run three jobs JobX, JobY, and JobZ where JobY should only run after JobX completes, but JobZ can run anytime in parallel. Which Laravel approach correctly handles this?
hard
A. Use job chaining for JobX and JobY, and dispatch JobZ separately.
B. Use job batching for all three jobs together.
C. Chain JobX, JobY, and JobZ in one chain to run sequentially.
D. Dispatch all three jobs separately without chaining or batching.

Solution

  1. Step 1: Understand job dependencies

    JobY depends on JobX finishing first, so they must run sequentially.
  2. Step 2: Consider JobZ's independence

    JobZ can run anytime, so it should run separately in parallel.
  3. Step 3: Choose correct Laravel approach

    Use chaining for JobX and JobY, and dispatch JobZ separately to run in parallel.
  4. Final Answer:

    Use job chaining for JobX and JobY, and dispatch JobZ separately. -> Option A
  5. Quick Check:

    Chain dependent jobs, dispatch independent jobs separately [OK]
Hint: Chain dependent jobs; dispatch independent jobs separately [OK]
Common Mistakes:
  • Batching all jobs when order matters only for some
  • Chaining all jobs forcing sequential run
  • Ignoring job dependencies