Memindahkan pekerjaan berat ke background: queue driver database/Redis, ShouldQueue, dispatch(), job chaining, retry & backoff, menjalankan worker dengan queue:work, dan dashboard Horizon untuk Redis queues.

Bayangkan sebuah request yang harus: menyimpan order, mengirim email, menghasilkan PDF, memanggil API pembayaran, dan notifikasi. Jika semuanya dijalankan sinkron di dalam request, user menunggu berdetik-detikk. Lebih buruk lagi: satu langkah gagal, seluruh request gagal. Queues memecahkan ini dengan memindahkan pekerjaan yang tidak harus segera selesai ke background worker.
Di episode ini kita pelajari pola dasarnya — dari mengirim job sampai menjalankan worker — dan mengenal Horizon, dashboard production-grade untuk queue berbasis Redis.
Alurnya: aplikasi menyimpan "pekerjaan" ke dalam queue dan segera mengembalikan response. Worker yang berjalan terus-menerus mengambil pekerjaan dan menjalankannya. User tidak menunggu — email/PDF/API call dikerjakan belakangan.
Queue driver diatur di .env lewat QUEUE_CONNECTION:
QUEUE_CONNECTION=database| Driver | Kapan dipakai |
|---|---|
sync | Default saat development — dieksekusi langsung (berguna untuk debug) |
database | Tanpa Redis, single server, cukup untuk skala menengah |
redis | Multi-server, throughput tinggi — standar production |
Untuk driver database, buat tabel job-nya:
php artisan queue:table
php artisan migratephp artisan make:job SendWelcomeEmail<?php
namespace App\Jobs;
use App\Models\User;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Queue\Queueable;
class SendWelcomeEmail implements ShouldQueue
{
use Queueable;
public function __construct(
public User $user,
) {
}
public function handle(): void
{
// kirim email - dijalankan worker, bukan di request
}
}Implementasi ShouldQueue memberi tahu Laravel: job ini harus masuk antrian, bukan dieksekusi sinkron.
use App\Jobs\SendWelcomeEmail;
SendWelcomeEmail::dispatch($user);Response langsung kembali ke user; handle() berjalan di worker. Untuk job yang hampir selalu ingin di-queue, bisa juga dispatchAfterResponse() — dieksekusi setelah response dikirim, tanpa perlu worker terpisah:
SendWelcomeEmail::dispatchAfterResponse($user);ProcessPayment::dispatch($order)->delay(now()->addMinutes(5));
SendInvoice::dispatch($order)
->chain([
new UpdateLedger($order),
new NotifyAccountant($order),
]);Job chaining menjalankan job berurutan; jika salah satu gagal, sisa chain tidak dijalankan — sempurna untuk pipeline yang saling bergantung.
Job bisa gagal — karena API down, network hiccup, dan sebagainya. Atur retry dan backoff di job:
class ProcessPayment implements ShouldQueue
{
public $tries = 3;
public $backoff = [5, 15, 60]; // tunggu 5s, lalu 15s, lalu 60s
public $timeout = 120; // batasi durasi eksekusi
public function failed(Throwable $e): void
{
// dipanggil setelah semua percobaan gagal
}
}failed() adalah tempat terakhir untuk mencatat atau mengirim alert. Job yang gagal permanen masuk tabel failed_jobs — audit dengan:
php artisan queue:failed
php artisan queue:retry all
php artisan queue:forget 1
php artisan queue:flushphp artisan queue:workphp artisan queue:work --queue=emails,default --tries=3 --sleep=2--queue memilih urutan antrian yang diproses.--tries membatasi percobaan; --sleep jeda saat queue kosong.Tip
Untuk development, jalankan php artisan queue:work di terminal terpisah saat menguji fitur yang memakai job. Untuk production, jangan lupa config:cache dan pastikan worker di-manage supervisor supaya restart otomatis saat crash — detail deployment-nya di episode 22.
Horizon adalah dashboard resmi Laravel untuk queue berbasis Redis — menampilkan job yang diproses, failed, throughput, dan queue balancing antar worker:
composer require laravel/horizon
php artisan horizon:install
php artisan migratephp artisan horizonphp artisan horizon menggantikan queue:work — ia mengelola worker pool secara otomatis sesuai beban, dengan dashboard di /horizon yang bisa dilindungi middleware auth. Horizon adalah jawaban Laravel untuk "bagaimana memantau dan menyeimbangkan queue di production".
Inti yang harus dibawa pulang:
ShouldQueue; kirim dengan dispatch().failed() untuk ketahanan.queue:work (daemon di production).Di episode 15 selanjutnya kita akan membahas events, listeners & notifications — make:event/make:listener, Event::dispatch, listeners, serta Notifications via mail/SMS/database dan broadcasting events real-time. Sampai jumpa di episode 15!