Laravel Queues Jobs Events Listeners Notifications
Selesai membaca dokumentasi ini?
Kembali ke rujukan utama Laravel untuk melanjutkan topik lainnya.
Kembali ke rujukan utama Laravel untuk melanjutkan topik lainnya.
Di Laravel, lima konsep ini sering dipakai bersama untuk memisahkan proses sinkron dan asinkron:
Kalau disederhanakan:
Di aplikasi Laravel yang tumbuh, tidak semua pekerjaan cocok dikerjakan langsung di request web. Kalau semua dipaksa sinkron, dampaknya biasanya cepat terasa:
Pemisahan queue, job, event, listener, dan notification membantu aplikasi tetap responsif, lebih mudah dirawat, dan lebih aman saat beban naik.
Tidak semua tugas perlu di-queue. Queue berguna saat pekerjaan tidak harus selesai sekarang juga dan boleh selesai beberapa detik atau menit kemudian.
Pindahkan ke queue kalau:
Jangan dipindah ke queue hanya karena “terlihat modern”. Queue menambah kompleksitas operasional: worker, retry, failed jobs, monitoring, dan idempotency.
Urutan ini penting:
Dengan cara ini, request user tidak harus menunggu seluruh pekerjaan selesai.
Queue adalah mekanisme antrean untuk menunda eksekusi task. Laravel mendukung beberapa driver queue, misalnya database, Redis, SQS, atau sync untuk mode tanpa antrean nyata.
ProcessPodcast::dispatch($podcast);Kalau ingin menunda eksekusi:
ProcessPodcast::dispatch($podcast)->delay(now()->addMinutes(5));Queue baru benar-benar bekerja kalau ada worker yang berjalan. Kalau tidak ada worker, job akan menumpuk dan tidak pernah diproses.
Job adalah kelas yang mewakili satu unit kerja. Job biasanya dipakai untuk tugas yang bisa dijalankan asinkron, misalnya mengirim email, memproses file, atau memanggil API eksternal.
Job biasanya punya:
handle() untuk menjalankan pekerjaantries, backoff, timeout, atau queue tertentuContoh sederhana:
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
class SendWelcomeEmail implements ShouldQueue
{
use Dispatchable
Pakai job saat kamu ingin:
Kalau job membawa model Eloquent, Laravel akan mencoba meng-serialize model tersebut dengan cara yang aman untuk queue. Tapi tetap hati-hati:
handle() bila perluEvent adalah sinyal domain atau aplikasi bahwa sesuatu sudah terjadi. Event bukan tempat melakukan semua pekerjaan; event hanya menandai fakta.
Contoh event:
UserRegisteredOrderPaidInvoiceGeneratedProfileUpdatedEvent cocok saat satu kejadian bisa memicu banyak aksi berbeda. Contohnya:
Event sebaiknya dipakai untuk memberi tahu bahwa sesuatu sudah terjadi. Logic inti tetap di service, action class, atau layer domain yang memang bertanggung jawab atas proses tersebut.
Listener adalah kelas yang merespons event tertentu. Satu event bisa punya banyak listener, dan tiap listener bisa menjalankan tugas yang berbeda.
Listener bisa dijalankan langsung atau dipindah ke queue.
Kalau listener mengimplementasikan ShouldQueue, Laravel akan memperlakukannya sebagai pekerjaan async.
use Illuminate\Contracts\Queue\ShouldQueue;
class SendWelcomeEmail implements ShouldQueue
{
public function handle(UserRegistered $event): void
{
// kirim email
}
}Event sebaiknya ringan. Listener memberi lapisan yang lebih jelas untuk side effect. Dengan begitu:
Notification adalah mekanisme Laravel untuk mengirim pesan ke penerima melalui berbagai channel.
Channel yang umum:
Notification cocok saat kamu perlu memberi tahu user atau sistem lain tentang suatu peristiwa, misalnya:
Notification juga bisa di-queue. Ini penting kalau channel pengiriman lambat atau jumlah penerimanya banyak.
use Illuminate\Notifications\Notification;
use Illuminate\Contracts\Queue\ShouldQueue;
class OrderPaidNotification extends Notification implements ShouldQueue
{
public function via($notifiable): array
{
return ['mail', 'database'];
}
Kalau notification di-queue, pengiriman pesan tidak menahan response utama.
Notification sering jadi pilihan lebih rapi daripada job biasa kalau tujuan utamanya memang mengabari user. Job lebih umum; notification lebih semantik.
Keempat mekanisme ini sering saling bertemu, tapi fungsinya tetap beda.
Pola yang umum:
Misalnya user berhasil mendaftar:
UserRegisteredContoh alur tersebut membuat controller tetap tipis dan side effect mudah ditambah tanpa mengubah alur utama.
Job sebaiknya membawa data minimum yang dibutuhkan. Kalau payload terlalu besar, serialization jadi berat dan job makin rentan gagal.
Karena job dieksekusi belakangan, data di database bisa sudah berubah. Jangan mengasumsikan state saat dispatch masih sama saat worker menjalankan job.
Job dan listener queued bisa dieksekusi ulang saat retry. Kalau tugasnya tidak idempotent, efek samping bisa dobel:
Solusinya biasanya dengan:
Kalau sesuatu harus selesai sebelum response dibentuk, jangan taruh di queued listener. Logic inti tetap perlu sinkron.
Task yang lambat tanpa timeout yang jelas bisa menumpuk. Task yang gagal tanpa backoff bisa terus mengulang dan membebani sistem.
Queue tanpa worker itu hanya penyimpanan job. Pastikan worker berjalan, restart saat deploy bila perlu, dan failed jobs dipantau.
Kalau job gagal, jangan cuma berharap retry menyelesaikan semuanya. Perlu observabilitas: log, failed job, alert, atau dashboard monitoring.
Kalau tujuannya bukan memberi tahu penerima, notification bukan pilihan utama. Gunakan job untuk pekerjaan umum, notification untuk pesan ke notifiable.
Pilih driver sesuai kebutuhan produksi:
sync untuk dev atau kasus sederhana tanpa worker nyatadatabase untuk setup yang cepat dan mudah dipahamiRedis untuk throughput yang lebih baikSQS atau managed queue lain untuk skala dan reliabilitas yang lebih tinggiUntuk job yang rentan gagal karena service eksternal, atur retry dan backoff agar sistem tidak spam request ke target yang sedang bermasalah.
Pastikan ada proses untuk:
Pemisahan yang sehat biasanya seperti ini:
Kalau kamu bingung harus pakai apa, pakai urutan ini: