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

tgif's avatar
Level 4

Jobs vs Events

Hello all, noob question for the masters. When would you choose to use a Laravel Job instead of an Event and vice versa. I'm having a little bit of trouble differentiating between the two. I think if I get more examples of how others have used them in the past I may get a better understanding.

0 likes
31 replies
mstnorris's avatar

@csuarez The way I see it.

Job

A Job is doing something.

  • RegisterUser
  • UpdateProfile
  • PublishArticle
  • SendReminderEmail

Event

An Event occurs when something happens/happened.

You can think of it as an Event occurs throughout different stages of a Job. In this case, and in most cases, an Event is defined in the past tense.

  • UserHasRegistered
  • ProfileWasUpdated
  • ArticleWasPublished
  • RemiderEmailWasSent
45 likes
beznez's avatar

The way that @mstnorris explains it is the way I think of it also. @JeffreyWay usually uses these examples:

  • PurchasePodcast Job
  • PodcastWasPurchased Event
5 likes
kajetons's avatar

Another way to look at it is that jobs are something that needs to be executed in order for application to work properly. Events are a side effect / result of those actions - while important and useful, they take a secondary role.

16 likes
gregrobson's avatar

@csuarez The above isn't quite following the Laravel terminology.

When the application is running you may have events (such as UserHasLoggedIn) that are picked up by listeners that may carry out actions like AddEntryToAuditLog. The important thing about these is that they start and end during the call to Laravel, and there's nothing to be done afterwards. http://laravel.com/docs/5.0/events

A job is something that may need to be done after Laravel has finished executing because it needs to be delayed (a follow-up email a day later) or takes a long time (e.g. preparing a zip backup of hosted files). These jobs are put into a queue using Laravel's provider or an external queue provider. The queue takes care of monitoring the pending jobs and running them according to the order they arrived and any scheduling requirements. http://laravel.com/docs/5.0/queues

There is some cross-over. An event could trigger a listener and register a job. E.g. A userRequestedBackup event fires - a listener picks up up the event to send a notification email, and a job is queued to zip up the files ready for sending. http://laravel.com/docs/5.0/events#queued-event-handlers

24 likes
tgif's avatar
Level 4

i c @gregrobson Thank you for the links. It seems to me that an event is used to handle UX whereas the job is used to handle core functionality of the application. I'll keep at it

1 like
mstnorris's avatar

@csuarez an Event doesn't have anything to do with UX directly.

It is just something that happens in the lifecycle of your system. Reactive

A Job on the other hand, you can think of as Proactive.

Kryptonit3's avatar

So a Job is for offloading tasks if I understand it correctly. I am assuming you wouldn't use a job for RegisterUser, UpdateProfile, PublishArticle but would for SendReminderEmail ?

I know you can, but is it bad practice to put all your insert/update logic in a Job?

Stephen's avatar

@Kryptonit3 Typically jobs are for things that should be pushed onto a queue but that isn't a requirement. Really, it just boils down to what behavior best translates the domain model.

bobbybouwmann's avatar

Sending emails, notifications and so on are jobs! You can queue them and do them later on.

So for example I want to register a user. There are a few things I want to do to get this going. First the user needs to fill in their credentials and I need to save that. That is one action. The second action would be sending an email to the user to tell them they need to confirm their registration.

Now you have two actions where one action can be queued and where one action ideally would be done at run time. So sending the email would be a job which can be called by an event of course.

UsersController extends Controller {

    public function store(UserRequest $request)
    {
        $user = $this->userRepository->store($request); // User is already stored here

        event(new UserWasRegistered($user); // Create some events

        redirect()->withSuccess('Awesome you are registered now! Confirm that email');
    }

}

Now we have that event we can just create some classes that will listen to that event

// app\Providers\EventServiceProvider.php

UserWasRegistered::class => [
    SendRegisteredEmail::class
    UpdateMemberCount::class
],

Now as you can see on the event the user was registered we call the SendRegisteredEmail class that will send the email to the user. We can add many actions here. Note that not all events needs to go to a queue. So for example UpdateMemberCount is clearing the cache of a query that get's the count of all the members. Now this is more a job then an event and it doesn't need to be queued at all. But it is still called by the event. Another example for deleting a user

/ app\Providers\EventServiceProvider.php

UserWasDeleted::class => [
    SendDeletedEmail::class
    UpdateMemberCount::class
],

As you can see we update the member count agian, well you get the idea

Note: I think I wondered off a bit...

8 likes
gregrobson's avatar

@pmall True - you could do that as well.

Looking at the previous comments, I think it depends on how we perceive scale? The email example is probably not the best…

"Quick and dirty" systems with few users: a simple Laravel Mail::send() will be fine - it won't add much to the request time.

However if you have 100 simultaneous requests coming in, then yes, you want to handle the request ASAP and get data back to the user. Any deferrable actions should be put onto a queue so that another process can send those emails (perhaps via Mandrill and some other Laravel background processing).

It will largely depend on your architecture -

2 likes
tgif's avatar
Level 4

i c. Using the term UX was a bad choice. But it does seem to me that event handling is experienced by the user immediately whereas jobs are more elaborate and so should be queued. And to determine what should be a job or an event is also dependant on the amount of traffic and purpose of your site. So if I'm making a site for my personal server to handle my plants Arduino sensors I can pretty much use events for everything. It is an extreme example but I think I get it.

Thank you all for the responses.

mr_luke's avatar

@csuarez I agree with @gregrobson but will try to explain it more clear:

Events are basically repercussion of some action that has taken place during your request lifecycle and causes sth that needs to be handled, like: SendNotification after Purchase. Events fire a Commands but can also be queue and then work like 'Jobs'.

Jobs are Commands/Tasks that work behind the scene.

3 likes
tgif's avatar
Level 4

@mr_luke I like your wording: repercussions vs tasks. Events are to user repercussions as jobs are to Commands/Tasks.

gregrobson's avatar

I agree with @mr_luke and @csuarez .... as Phil Karlton put it: "There are only two hard things in Computer Science: cache invalidation and naming things."

1 like
pmall's avatar

I like to think about events as something that is not crucial for the application. Something that could fail sometimes without causing major problem. Sending notification email failed one time ? ok no big deal.

1 like
sarahjii's avatar

@dev_droid, Events make it really easy for developers like us to hook on to or extend the underlying architecture of the framework in a clean and maintainable way. It also makes it really easy for us to create events for our own applications so that we create software that is easier to extend and maintain for others.

stueynet's avatar

Sorry for re-opening this but its a great discussion. But just wanted to be clear. If you have a listener class that listens to an event, and also implements ShouldQueue, is this any different from queuing a job directly? In my application I use events to handle most of the important transactions like registration, checkout etc... The event has listeners that do things when the event happens. One of those would be to send an email when a user receives a direct message. On those slower processes I implement ShouldQueue in the Listener class. Example:

class NotifyUserOfMessage implements ShouldQueue {

    /**
     * Create the event listener.
     *
     * @param Mailer $mailer
     *
     * @return \App\Listeners\NotifyUserOfMessage
     */
    public function __construct(Mailer $mailer)
    {
        $this->mailer = $mailer;
    }

    /**
     * Handle the event.
     *
     * @param MessageWasCreated $event
     *
     * @return void
     */
    public function handle(MessageWasCreated $event)
    {
    // send the email here without firing a job. Just fire the email since the Listener already Queues.
    }

Is this problematic? Would it make more sense to bring the concept of Jobs into this workflow?

stueynet's avatar

Here is another example where I call stripe within the Event Listener. Bad or good?

class ChargeUserUponCompletion implements ShouldQueue {

    /**
     * @var PaymentServiceInterface
     */
    private $stripe;

    /**
     * Create the event listener.
     *
     * @param PaymentServiceInterface $stripe
     */
    public function __construct(PaymentServiceInterface $stripe)
    {
        $this->stripe = $stripe;
    }

    /**
     * Handle the event.
     *
     * @param  ConsultWasCompleted    $event
     */
    public function handle(ConsultWasCompleted $event)
    {       
        $charge = $this->stripe->retrieve($consult->getStripeToken())
    }
}

jekinney's avatar

If it works it really isn't bad. Where something could be better is a matter of opinion.

1 like
stueynet's avatar

Thanks @jekinney. I guess what I am trying to figure out is that if a Listener with ShouldQueue is the same as pushing a Job.

stueynet's avatar

So just a follow up here on my discovery and direction now. I have found that a fundamental issue arises out of using events in this way. For example relaying solely on an event to do something like sending a notification of some kind. So in the current structure, the controller raises the event. And you listen for the event in EventServiceProvider and then delegate to a listener which ultimately fires the notification. Perhaps this happens when a new reply is added to a user's thread.

The problem here is that, sometimes you may not want to send a notification. But that doesn't mean the event didn't happen. So tying the notification to the event happening is problematic. In this case a Job is much more suitable because you can both raise the event, and dispatch a job if applicable. So the event always happens. And maybe you have listeners on it. But if the notification being sent is based on some other condition, a Job is much more useful here.

1 like
goatshark's avatar

@stueynet: True. You could also let the event listener decide whether or not to send the notification. That's assuming you're using something, user preferences perhaps, to determine whether or not to send notifications. My apologies if this makes you re-re-re-think things. For what it's worth, I have a couple of strategies that I use to decide whether a Job or an Event/Listeners is appropriate for any given situation.

  1. If I need to take multiple, unrelated to one another, actions when something in my application happens, I use Events/Listeners.
  2. If I just need to take a single action, I use a Job. .....and since things change as I build out my application, it isn't rare for me to first build a Job for something and then later change it to an event/listeners scenario. That said, my third strategy seems to be my go-to most weeks:
  3. I check my mood, evaluate my feelings, maybe have a good cry - and then decide if I'm in more a Job mood or an Event/Listeners mood. I can always change it later.
8 likes
stueynet's avatar

@goatshark this is logical. I think my reasoning at this point will be that event listeners do fire where the event happens. So anything that happens in the app, will cause an event. The ServiceProvider registers listeners and those listeners do what they are supposed when the event happens. They don't decide to do their thing or not.

In the case of the above, the controller receives an API call. That API call may contain information that dictates whether a notification is to be sent or not. So if it should be sent, we dispatch the notification job. But always fire the event.

If we put the logic for doing stuff within the listener itself, it also works but you then have to pass down additional information to the Event and look for it within the listener. I think I prefer for the system to be more explicit. So the logic would be:

A new message was created:

  • Raise the event because it happened
  • Create listeners for the event that will always do something when that event happens
  • Dispatch a notification from the controller if the data dictates it

That way I raise an event like MessageWasCreated($message) instead of MessageWasCreate($message, $otherdata).

goatshark's avatar

@stueynet: Totally gotcha. I like how you think too - I've changed from Event/Listeners to a Job at times for the very reason you bring up - I realized that the logic I included in the Listener bugged me because, at times, it dictated that there was nothing to be done..... therefore, it was being utilized even when it wouldn't do anything. Not that that's horrible, but it did bug me a little to think about it always running even when it ends up doing nothing. For me, it doesn't end up mattering that much because rarely am I actually concerned about performance considering 9 out of 10 of my applications never make it out of Homestead. It's good stuff to think about though.

1 like
embercom's avatar

To piggy-back, because I enjoyed this discussion, I also like to think of events as useful for two things:

(1) Events are great if you want to mentally decouple different systems. An Order may fire that it went from drafted to created, but it arguably wouldn't know anything about PaymentProcessing. Firing the job ProcessPayment within an Order method adds some minor context of the payment system, and although it's not a huge context, you might forget to look in your Orders namespace when debugging a Payment failure.

(2) Events are great when you know there are going to be many listeners, whereas a job is a kind of one time thing. Following the example above, when an Order is created there may be many things that need happen across your app, including payments, shipping, notifications, updating sales data, etc.

That's at least how I've been thinking about it. Cheers!

4 likes
gauravmak's avatar

Now that Event Listeners can also be queued, a Job limits us to a single task while Event-Listeners combo can allow us to perform more tasks for a single update in my opinion.

1 like
right_click's avatar

great conversation.........i do have this thing though, im trying to learn events, but then when i try to fire one up,it appears i need to create a jobs table first. does every event have to be stored.....especially if the listener is not implementing the ShouldQueue interface?

Tray2's avatar

@right_click Why do you ask questions in a 6 year old thread. Open a new one if you want to ask a question instead of highjacking an really old thread,

Please or to participate in this conversation.