Posted on under Laravel by Owen Conti.
Out of the box, Laravel has a great API for dispatching jobs:
1<?php2 3ProcessPodcast::dispatch($podcast);
That will dispatch the
ProcessPodcast
job, with the
$podcast
being passed in for the job to use as it wants.
Under the hood, Laravel is doing the following:
SerializesModels
trait, the identifier of the passed Model is serialized as the payload of the jobThis all works very well and makes using Laravel's Queue system a breeze!
🚨🚨 There's a catch! 🚨🚨
Laravel is trying to be extra helpful by also serializing the loaded relations, and then eagerly loads them when the job is processed.
So let's say in order to dispatch the
ProcessPodcast
job, you have to load 5 relations on the
Podcast
model. When the
ProcessPodcast
job is processed from the queue, all 5 of those relations (and any of their loaded nested relations) are eagerly loaded.
Depending on your application and the logic of your job, this may make a significant impact on your queue's processing time.
If your job needs to use the relations to dispatch the job, but does not need those relations when processing the job, you can instead pass the identifier of the model instead of the model itself. It's a little bit more work on your end, because you'll be responsible for pulling the model out of the database on your own, but it also gives you more control.
Now when dispatching your job, you can do this:
1<?php2 3ProcessPodcast::dispatch($podcast->id);
And inside your job's class:
1<?php 2 3public function __construct(int $podcastId) 4{ 5 $this->podcastId = $podcastId; 6} 7 8public function handle() 9{10 $podcast = Podcast::findOrFail($this->podcastId);11}
In the application I found this issue on, the processing time of one of our jobs went from ~8 seconds down to ~1 second.
Hopefully you found this article useful! If you did, share it on X!
Found an issue with the article? Submit your edits against the repository.