Pernahkah pengguna aplikasi Anda menunggu lama setelah menekan tombol "Kirim", hanya karena di balik layar aplikasi sedang mengirim email atau memproses gambar? Tugas berat seperti itu tidak seharusnya membuat pengguna menunggu. Di sinilah Queue dan Job berperan: mereka memindahkan pekerjaan berat ke latar belakang sehingga respons ke pengguna tetap cepat. Tutorial ini membahas Queue di Laravel 10/11 dari nol dengan kode nyata.
Kenapa Butuh Queue?
Secara default, setiap request diproses secara sinkron — pengguna menunggu sampai semua kode selesai. Jika sebuah aksi memicu pengiriman 100 email atau kompresi gambar 5 MB, request bisa memakan waktu beberapa detik. Dengan queue, Anda cukup menitipkan pekerjaan itu ke antrian, mengembalikan respons instan ke pengguna, dan membiarkan proses worker menyelesaikannya di belakang layar.
- Respons lebih cepat: pengguna tidak menunggu tugas berat.
- Tahan beban: lonjakan pekerjaan diproses bertahap, bukan sekaligus.
- Retry otomatis: job yang gagal bisa dicoba ulang tanpa mengganggu pengguna.
1. Konfigurasi Driver Queue
Laravel mendukung beberapa driver: sync (default, langsung dijalankan), database, redis, dan lainnya. Untuk mulai, driver database paling mudah karena tidak butuh layanan tambahan. Atur di file .env:
QUEUE_CONNECTION=database
Lalu buat tabel penyimpan job dan jalankan migrasinya:
php artisan make:queue-table
php artisan migrate
Untuk trafik tinggi, redis jauh lebih cepat. Cukup ubah menjadi QUEUE_CONNECTION=redis setelah server Redis tersedia — kode job Anda tidak perlu diubah sama sekali.
2. Membuat Job Pertama
Buat kelas job dengan artisan:
php artisan make:job SendWelcomeEmail
File tercipta di app/Jobs/SendWelcomeEmail.php. Kirim data yang dibutuhkan lewat constructor, dan taruh logika berat di method handle():
class SendWelcomeEmail implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
public function __construct(public User $user) {}
public function handle(): void
{
Mail::to($this->user->email)
->send(new WelcomeMail($this->user));
}
}
Kunci di sini adalah interface ShouldQueue — inilah yang memberi tahu Laravel bahwa job ini harus diantrikan, bukan dijalankan langsung.
3. Men-dispatch Job
Dari controller, cukup panggil dispatch():
public function store(Request $request)
{
$user = User::create($request->validated());
SendWelcomeEmail::dispatch($user);
return redirect()->route('dashboard')
->with('success', 'Akun dibuat, email menyusul.');
}
Perhatikan bahwa respons dikembalikan seketika. Job masuk antrian, dan pengiriman email terjadi di belakang layar. Anda juga bisa menunda job dengan delay():
SendWelcomeEmail::dispatch($user)->delay(now()->addMinutes(5));
4. Menjalankan Worker
Job yang di-dispatch hanya tersimpan di antrian; sesuatu harus mengeksekusinya. Jalankan worker:
php artisan queue:work
Worker akan terus berjalan, mengambil job satu per satu, dan menjalankan method handle(). Untuk pengembangan, gunakan queue:listen yang otomatis memuat ulang kode. Untuk produksi, gunakan queue:work karena lebih efisien.
Penting: setelah mengubah kode job, restart worker agar perubahan terbaca:
php artisan queue:restart
5. Retry dan Failed Jobs
Job bisa gagal — koneksi SMTP putus, API pihak ketiga error. Laravel bisa mencoba ulang secara otomatis. Atur batas percobaan lewat properti pada job:
public $tries = 3;
public $backoff = 10; // jeda 10 detik antar percobaan
Jika semua percobaan habis, job masuk ke tabel failed_jobs. Siapkan tabelnya:
php artisan make:queue-failed-table
php artisan migrate
Lihat, coba ulang, atau hapus job yang gagal:
php artisan queue:failed
php artisan queue:retry all
php artisan queue:flush
Anda juga bisa menangani kegagalan secara khusus dengan method failed() di job, misalnya untuk mengirim notifikasi ke admin.
6. Contoh Nyata: Memproses Gambar
Kompresi dan pembuatan thumbnail termasuk tugas berat. Bungkus dalam job:
class ProcessProductImage implements ShouldQueue
{
use Dispatchable, Queueable, SerializesModels;
public function __construct(public Product $product) {}
public function handle(): void
{
$img = Image::read($this->product->image_path)
->scale(width: 800);
$img->save(storage_path('app/public/thumbnails/'
. $this->product->id . '.jpg'));
}
}
Dispatch setelah upload selesai, dan pengguna tidak perlu menunggu proses gambar rampung.
7. Menjaga Worker Tetap Hidup dengan Supervisor
Di server produksi, proses queue:work bisa mati kapan saja. Supervisor adalah pengawas proses di Linux yang otomatis menghidupkan ulang worker. Contoh konfigurasi /etc/supervisor/conf.d/laravel-worker.conf:
[program:laravel-worker]
command=php /var/www/app/artisan queue:work --tries=3 --timeout=90
autostart=true
autorestart=true
numprocs=2
user=www-data
redirect_stderr=true
stdout_logfile=/var/www/app/storage/logs/worker.log
Muat konfigurasi:
sudo supervisorctl reread
sudo supervisorctl update
sudo supervisorctl start laravel-worker:*
Dengan begitu, worker selalu berjalan meski server di-restart. Kini aplikasi Anda menangani tugas berat tanpa membuat pengguna menunggu — pola yang sama bisa dipakai untuk laporan, notifikasi WhatsApp, ekspor Excel, dan proses batch lainnya.
Kapan Sebaiknya Memakai Queue
Tidak semua proses perlu dijalankan lewat antrean, jadi kenali kapan queue benar-benar bermanfaat. Gunakan queue untuk tugas yang memakan waktu atau tidak perlu diselesaikan seketika, seperti mengirim email massal, memproses gambar, menghasilkan laporan besar, atau memanggil layanan pihak ketiga yang lambat. Dengan memindahkan pekerjaan berat ke latar belakang, respons aplikasi kepada pengguna tetap cepat. Sebaliknya, tugas ringan yang butuh hasil langsung tidak perlu di-queue. Pastikan job dirancang idempoten sehingga aman bila dijalankan ulang saat gagal, dan tetapkan mekanisme percobaan ulang serta penanganan kegagalan yang jelas. Pantau worker agar selalu berjalan dan tumpukan antrean tidak menumpuk. Untuk beban tinggi, pertimbangkan driver yang andal seperti Redis. Dengan penerapan queue yang tepat, aplikasi Anda menjadi lebih responsif dan tahan terhadap lonjakan pekerjaan berat.
Pertanyaan Umum (FAQ)
Apa bedanya queue dan job? Job adalah unit pekerjaan yang ingin dijalankan, sedangkan queue adalah antrean tempat job menunggu untuk diproses oleh worker di latar belakang.
Driver queue apa yang sebaiknya dipakai? Untuk skala kecil, driver database sudah cukup. Untuk beban tinggi dan performa lebih baik, Redis sangat disarankan karena cepat dan andal.
Bagaimana bila job gagal? Tetapkan jumlah percobaan ulang dan tangani kegagalan lewat metode khusus, lalu pantau tabel job gagal agar tidak ada pekerjaan penting yang terlewat tanpa penanganan.