MAXBY SSD 512GB/1TB M.2 NVMe PCIe Gen4x4 SSD NVMe Gen3/1TB PCIe 4.0 Garansi Resmi 5 Tahun Original

Laravel Task Scheduling: Cara Menjalankan Command Secara Berkala

Apa Itu Laravel Task Scheduling?

Laravel Task Scheduling adalah fitur Laravel yang digunakan untuk menjalankan task secara otomatis berdasarkan jadwal tertentu.

Misalnya aplikasi membutuhkan proses:

  • Menghapus data sementara setiap hari
  • Mengirim laporan setiap pagi
  • Membersihkan cache secara berkala
  • Memproses data setiap beberapa menit
  • Menjalankan Artisan Command
  • Menjalankan Queue Job berdasarkan jadwal
  • Membersihkan file lama
  • Mengirim notifikasi otomatis

Tanpa Laravel Scheduler, kita biasanya perlu membuat banyak konfigurasi Cron secara terpisah.

Dengan Laravel Scheduler, jadwal dapat dikelola dari aplikasi Laravel.

Contohnya:

Laravel Scheduler
      ↓
Setiap menit
      ↓
Periksa task
      ↓
Task sesuai jadwal?
      ↓
Jalankan

Kenapa Menggunakan Laravel Scheduler?

Tanpa Scheduler, kita mungkin membuat banyak Cron Job:

Cron 1 → cleanup
Cron 2 → report
Cron 3 → notification
Cron 4 → backup
Cron 5 → sync data

Konfigurasi tersebut dapat menjadi sulit dipelihara.

Dengan Laravel Scheduler:

Cron
 ↓
Laravel Scheduler
 ├── cleanup
 ├── report
 ├── notification
 ├── backup
 └── sync data

Server hanya perlu memanggil Laravel Scheduler secara berkala, sedangkan jadwal task dikelola di aplikasi.

Contoh Penggunaan Task Scheduling

Misalnya kita ingin menjalankan Command setiap hari:

Setiap hari pukul 01:00
        ↓
Laravel Scheduler
        ↓
cleanup:temporary-data

Atau:

Setiap 5 menit
        ↓
Sync data

Atau:

Setiap hari pukul 08:00
        ↓
Kirim laporan

Laravel Scheduler dan Cron

Laravel Scheduler tetap membutuhkan mekanisme dari server untuk memicunya.

Pada Linux/Ubuntu, biasanya digunakan Cron.

Konsepnya:

Ubuntu Cron
     ↓
Laravel Scheduler
     ↓
Task

Cron bertugas memanggil Scheduler.

Laravel kemudian menentukan task mana yang harus dijalankan.

Membuat Artisan Command

Salah satu cara yang umum adalah membuat Artisan Command.

Misalnya:

php artisan make:command CleanupTemporaryData

Laravel akan membuat file Command di:

app/Console/Commands/CleanupTemporaryData.php

Contoh sederhana:

<?php

namespace App\Console\Commands;

use Illuminate\Console\Command;

class CleanupTemporaryData extends Command
{
    protected $signature = 'cleanup:temporary-data';

    protected $description = 'Membersihkan data sementara';

    public function handle()
    {
        $this->info('Cleanup selesai.');

        return self::SUCCESS;
    }
}

Sekarang kita memiliki Command:

php artisan cleanup:temporary-data

Menjalankan Command Secara Manual

Sebelum memasukkannya ke Scheduler, selalu tes Command secara manual.

php artisan cleanup:temporary-data

Jika menghasilkan:

Cleanup selesai.

berarti Command dapat dijalankan.

Ini penting karena jika Command sendiri error, Scheduler juga tidak akan menyelesaikan task tersebut.

Menentukan Jadwal Task

Setelah Command siap, kita dapat memasukkannya ke Scheduler.

Pada versi Laravel tertentu, konfigurasi scheduling dapat berada di:

routes/console.php

Contoh:

use Illuminate\Support\Facades\Schedule;

Schedule::command('cleanup:temporary-data')
    ->daily();

Artinya Command:

php artisan cleanup:temporary-data

akan dijalankan satu kali setiap hari.

Lokasi konfigurasi Scheduler dapat berbeda tergantung versi Laravel. Karena itu, gunakan struktur scheduling yang sesuai dengan versi Laravel yang digunakan project.

Menjalankan Task Setiap Menit

Jika ingin menjalankan Command setiap menit:

Schedule::command('cleanup:temporary-data')
    ->everyMinute();

Konsepnya:

00:00 → Run
00:01 → Run
00:02 → Run
00:03 → Run
...

Namun jangan menggunakan everyMinute() untuk task berat tanpa mempertimbangkan resource server.

Menjalankan Task Setiap Lima Menit

Gunakan:

Schedule::command('cleanup:temporary-data')
    ->everyFiveMinutes();

Task akan dijalankan:

10:00
10:05
10:10
10:15
...

Interval lain yang tersedia dapat digunakan sesuai kebutuhan aplikasi.

Menjalankan Task Setiap Jam

Untuk task setiap jam:

Schedule::command('cleanup:temporary-data')
    ->hourly();

Misalnya:

01:00
02:00
03:00
04:00
...

Ini cocok untuk proses seperti sinkronisasi data yang tidak membutuhkan interval terlalu pendek.

Menjalankan Task Setiap Hari

Gunakan:

Schedule::command('cleanup:temporary-data')
    ->daily();

Secara default, task akan dijalankan sekali sehari pada waktu yang ditentukan oleh scheduler Laravel.

Jika ingin menentukan jam tertentu, gunakan:

Schedule::command('cleanup:temporary-data')
    ->dailyAt('01:00');

Artinya:

Setiap hari
pukul 01:00

Menjalankan Task Setiap Hari pada Jam Tertentu

Contoh mengirim laporan setiap pukul 08:00:

Schedule::command('report:daily')
    ->dailyAt('08:00');

Contoh lain:

Schedule::command('backup:database')
    ->dailyAt('02:00');

Ini cocok untuk task yang ingin dijalankan pada waktu tertentu.

Menjalankan Task Mingguan

Untuk task setiap minggu:

Schedule::command('report:weekly')
    ->weekly();

Jika ingin menentukan hari dan jam, gunakan konfigurasi yang sesuai dengan kebutuhan.

Misalnya task laporan setiap Senin pukul 08:00:

Schedule::command('report:weekly')
    ->weeklyOn(1, '08:00');

Pada konfigurasi tersebut:

1 = Monday
08:00 = waktu eksekusi

Menjalankan Task Bulanan

Untuk task setiap bulan:

Schedule::command('report:monthly')
    ->monthly();

Misalnya laporan bulanan:

Schedule::command('report:monthly')
    ->monthlyOn(1, '08:00');

Artinya task dijadwalkan pada tanggal 1 setiap bulan pukul 08:00.

Menjalankan Job dengan Scheduler

Scheduler tidak hanya dapat menjalankan Artisan Command.

Kita juga dapat menjalankan Queue Job.

Misalnya:

Schedule::job(new SendDailyReport)
    ->dailyAt('08:00');

Alurnya:

Scheduler
    ↓
08:00
    ↓
SendDailyReport
    ↓
Queue
    ↓
Queue Worker

Pendekatan ini sangat berguna untuk task yang membutuhkan proses background.

Scheduler dan Queue Bisa Digabungkan

Misalnya setiap jam aplikasi harus melakukan sinkronisasi data.

Kita bisa menggunakan:

Schedule::job(new SyncProducts)
    ->hourly();

Kemudian Queue Worker yang memproses Job:

Cron
 ↓
Scheduler
 ↓
SyncProducts Job
 ↓
Redis
 ↓
Queue Worker
 ↓
Process

Dengan demikian Scheduler tidak harus melakukan seluruh pekerjaan secara langsung.

Scheduler vs Queue

Keduanya memiliki fungsi berbeda.

Scheduler menentukan:

Kapan task dijalankan?

Queue menentukan:

Bagaimana pekerjaan diproses di background?

Contoh:

Scheduler
 ↓
Setiap pukul 08:00
 ↓
Dispatch Job
 ↓
Queue
 ↓
Worker

Ini merupakan pola yang sangat berguna pada aplikasi Laravel production.

Menjalankan Closure

Laravel Scheduler juga dapat menjalankan Closure.

Contoh:

Schedule::call(function () {
    logger()->info('Scheduler berjalan');
})->daily();

Ini cocok untuk task sederhana.

Namun untuk logic yang kompleks, lebih baik gunakan Artisan Command atau Job agar kode tetap mudah dirawat.

Menjalankan Shell Command

Scheduler juga dapat menjalankan command melalui:

Schedule::exec('php /path/to/script.php')
    ->daily();

Namun hati-hati ketika menjalankan command sistem.

Pastikan:

  • Path benar
  • User memiliki permission
  • Command aman
  • Environment sesuai
  • Output/error dapat dilacak

Untuk logic yang merupakan bagian dari aplikasi Laravel, Artisan Command biasanya lebih mudah dipelihara.

Memeriksa Task yang Terdaftar

Laravel menyediakan command:

php artisan schedule:list

Command tersebut dapat membantu melihat task yang terdaftar dan jadwalnya.

Contohnya Anda mungkin melihat:

0 1 * * *   cleanup:temporary-data
0 8 * * *   report:daily
*/5 * * * * sync:products

Jika task tidak muncul di schedule:list, periksa konfigurasi Scheduler terlebih dahulu.

Cara Menjalankan Scheduler Secara Lokal

Untuk development, kita dapat menjalankan:

php artisan schedule:work

Laravel akan menjalankan scheduler secara terus-menerus.

Konsepnya:

schedule:work
      ↓
Menunggu jadwal
      ↓
Task waktunya tiba
      ↓
Task dijalankan
      ↓
Menunggu lagi

Ini sangat berguna untuk testing.

schedule:work vs Cron

Ada dua konsep penting.

schedule:work

Laravel menjalankan proses scheduler yang terus aktif.

php artisan schedule:work

Cron

Server menjalankan Scheduler setiap menit:

* * * * * cd /var/www/example.com && php artisan schedule:run

Untuk production, Cron biasanya menjadi pilihan sederhana karena Scheduler Laravel tidak perlu berjalan sebagai long-running process.

Konfigurasi Cron di Ubuntu

Edit Cron user:

crontab -e

Kemudian tambahkan:

* * * * * cd /var/www/example.com && php artisan schedule:run >> /dev/null 2>&1

Artinya setiap menit Ubuntu akan menjalankan:

php artisan schedule:run

Laravel kemudian menentukan task mana yang waktunya sudah tiba.

Kenapa Cron Hanya Setiap Menit?

Pertanyaan umum adalah:

Kalau task dijalankan setiap hari, kenapa Cron tetap setiap menit?

Karena Laravel Scheduler yang menentukan apakah task harus dieksekusi.

Misalnya:

00:00 → schedule:run
00:01 → schedule:run
00:02 → schedule:run
...
08:00 → schedule:run
          ↓
       report:daily

Jadi Cron hanya bertugas memanggil Scheduler.

Pastikan Path Laravel Benar

Contoh:

* * * * * cd /var/www/example.com && php artisan schedule:run >> /dev/null 2>&1

Pastikan:

/var/www/example.com

merupakan directory project Laravel yang benar.

Cek:

cd /var/www/example.com
ls

Harus terdapat file seperti:

artisan
composer.json
app/
config/
routes/
storage/

Gunakan Absolute Path PHP pada Cron

Jika Cron tidak menemukan php, gunakan absolute path.

Cari:

which php

Misalnya:

/usr/bin/php

Cron dapat ditulis:

* * * * * cd /var/www/example.com && /usr/bin/php artisan schedule:run >> /dev/null 2>&1

Ini dapat menghindari masalah PATH yang berbeda antara shell biasa dan Cron.

Pastikan Cron Service Berjalan

Di Ubuntu:

sudo systemctl status cron

Jika belum berjalan:

sudo systemctl start cron

Dan agar otomatis aktif setelah reboot:

sudo systemctl enable cron

Nama service dapat berbeda pada distribusi Linux tertentu, tetapi pada Ubuntu umumnya menggunakan cron.

Cek Cron yang Terpasang

Gunakan:

crontab -l

Pastikan terdapat:

* * * * * cd /var/www/example.com && /usr/bin/php artisan schedule:run >> /dev/null 2>&1

Jika tidak ada, Scheduler tidak akan dipanggil oleh Cron.

Masalah Scheduler Tidak Berjalan

Jika task tidak dijalankan, jangan langsung menyalahkan Laravel.

Periksa urutannya:

Cron
 ↓
schedule:run
 ↓
Scheduler
 ↓
Task
 ↓
Command/Job

Mulai dari Cron.

Tes schedule:run Secara Manual

Masuk ke project:

cd /var/www/example.com

Kemudian:

php artisan schedule:run

Jika task sedang waktunya dijalankan, Laravel akan menjalankannya.

Jika tidak ada task yang harus dijalankan, Anda mungkin tidak melihat output yang berarti.

Untuk debugging, gunakan:

php artisan schedule:list

Gunakan schedule:list untuk Debugging

Misalnya terdapat:

Schedule::command('report:daily')
    ->dailyAt('08:00');

jalankan:

php artisan schedule:list

Periksa apakah task muncul.

Jika tidak muncul:

Scheduler configuration

perlu diperiksa.

Jika muncul tetapi tidak berjalan:

Cron
Environment
Timezone
Command

perlu diperiksa.

Perhatikan Timezone

Timezone merupakan salah satu penyebab Scheduler berjalan pada waktu yang tidak sesuai.

Misalnya Anda mengharapkan:

08:00 WIB

tetapi server menggunakan:

UTC

Task bisa berjalan pada waktu yang berbeda dari ekspektasi.

Periksa konfigurasi aplikasi:

'timezone' => 'Asia/Jakarta',

di konfigurasi Laravel sesuai kebutuhan aplikasi.

Anda juga dapat menentukan timezone pada task tertentu:

Schedule::command('report:daily')
    ->dailyAt('08:00')
    ->timezone('Asia/Jakarta');

Ini berguna ketika server atau aplikasi melayani timezone tertentu.

Timezone Server vs Timezone Laravel

Ada dua hal yang perlu dibedakan:

Server timezone

dan:

Laravel application timezone

Misalnya server menggunakan:

UTC

tetapi aplikasi menggunakan:

Asia/Jakarta

Ini tidak selalu menjadi masalah selama konfigurasi Scheduler dipahami dengan benar.

Yang penting adalah menentukan timezone yang memang diinginkan aplikasi.

Hindari Task yang Berjalan Tumpang Tindih

Misalnya sebuah task dijadwalkan:

Schedule::command('report:generate')
    ->everyMinute();

tetapi prosesnya membutuhkan:

3 menit

Maka task berikutnya berpotensi mulai sebelum task sebelumnya selesai.

Konsepnya:

00:00 → Task A mulai
00:01 → Task B mulai
00:02 → Task C mulai
00:03 → Task A selesai

Jika task tidak dirancang untuk berjalan paralel, ini dapat menyebabkan masalah.

Gunakan withoutOverlapping()

Untuk mencegah task yang sama berjalan bersamaan:

Schedule::command('report:generate')
    ->everyMinute()
    ->withoutOverlapping();

Konsepnya:

Task A
 ↓
Sedang berjalan
 ↓
Task berikutnya?
 ↓
Skip karena masih running

Ini sangat berguna untuk task yang membutuhkan waktu lama.

Mengatur Lock withoutOverlapping

Anda dapat menentukan berapa lama lock dianggap valid.

Contoh:

Schedule::command('report:generate')
    ->everyMinute()
    ->withoutOverlapping(10);

Nilainya perlu disesuaikan dengan karakteristik task.

Jika task biasanya membutuhkan 5 menit, timeout lock jangan terlalu pendek.

Menjalankan Task Hanya di Environment Tertentu

Misalnya task tertentu hanya boleh berjalan di production.

Gunakan:

Schedule::command('cleanup:temporary-data')
    ->daily()
    ->environments(['production']);

Dengan begitu task tidak dijalankan pada environment lain seperti development atau testing.

Ini sangat berguna agar task production tidak sengaja dijalankan di lokal.

Menjalankan Task di Server Tertentu

Pada aplikasi yang menggunakan beberapa server, perlu berhati-hati.

Misalnya:

Server A
Server B
Server C

Jika semuanya menjalankan Scheduler:

A → schedule:run
B → schedule:run
C → schedule:run

task tertentu bisa dijalankan lebih dari sekali.

Untuk kebutuhan seperti ini, Laravel menyediakan mekanisme seperti:

->onOneServer()

dengan kondisi dan konfigurasi cache yang sesuai.

Contohnya:

Schedule::command('report:daily')
    ->daily()
    ->onOneServer();

Gunakan ini ketika Scheduler memang berjalan pada beberapa server dan Anda ingin task hanya dieksekusi oleh satu server.

Task Scheduling pada Multiple Server

Tanpa mekanisme koordinasi:

Server A → Task
Server B → Task
Server C → Task

Akibatnya satu task dapat dieksekusi tiga kali.

Dengan onOneServer() dan cache/lock yang dikonfigurasi dengan benar:

Server A ─┐
Server B ─┼→ Lock → Satu server menjalankan task
Server C ─┘

Ini penting untuk aplikasi yang sudah menggunakan load balancing atau horizontal scaling.

Mengirim Output Task ke File

Untuk command tertentu, Anda dapat mengarahkan output ke file.

Contoh:

Schedule::command('report:daily')
    ->dailyAt('08:00')
    ->appendOutputTo(storage_path('logs/report-scheduler.log'));

Dengan begitu, output Command dapat diperiksa ketika terjadi masalah.

Mengirim Output ke Email

Untuk kebutuhan tertentu, output task dapat diarahkan ke email menggunakan fitur scheduling yang sesuai.

Namun untuk production, biasanya lebih baik menggunakan logging dan monitoring yang terstruktur daripada mengirim semua output task melalui email.

Menjalankan Task Setelah Task Lain

Terkadang kita memiliki dependensi:

Import Data
   ↓
Process Data
   ↓
Generate Report

Scheduler menyediakan kemampuan untuk mengatur alur tertentu, tetapi sebaiknya task yang saling bergantung secara kuat dipertimbangkan untuk dibuat sebagai Job chain atau workflow yang lebih jelas.

Jangan membuat dependency yang kompleks hanya melalui banyak jadwal terpisah jika urutannya sangat penting.

Scheduler untuk Database Cleanup

Contoh task:

Schedule::command('cleanup:temporary-data')
    ->dailyAt('02:00');

Command:

public function handle()
{
    TemporaryData::where(
        'created_at',
        '<',
        now()->subDays(7)
    )->delete();

    return self::SUCCESS;
}

Dengan demikian data yang lebih lama dari 7 hari dapat dibersihkan secara otomatis.

Tetap pertimbangkan ukuran data dan beban database sebelum melakukan operasi delete dalam jumlah besar.

Scheduler untuk Mengirim Laporan

Misalnya:

Schedule::job(new SendDailyReport)
    ->dailyAt('08:00');

Alurnya:

08:00
 ↓
Scheduler
 ↓
SendDailyReport
 ↓
Redis
 ↓
Queue Worker
 ↓
Email

Ini merupakan pola yang lebih baik daripada membuat Scheduler melakukan proses berat secara langsung.

Scheduler untuk Sinkronisasi API

Misalnya aplikasi perlu mengambil data dari API eksternal setiap 10 menit:

Schedule::job(new SyncExternalProducts)
    ->everyTenMinutes();

Kemudian:

Scheduler
 ↓
SyncExternalProducts
 ↓
Queue
 ↓
Worker
 ↓
External API
 ↓
Database

Jika API lambat atau mengalami masalah, Queue Worker dapat menangani proses tersebut tanpa membuat Scheduler menjadi terlalu berat.

Jangan Menaruh Proses Berat di Scheduler

Hindari:

Schedule::call(function () {
    // proses jutaan data
    // request API dalam jumlah besar
    // generate report besar
})->daily();

Lebih baik:

Scheduler
 ↓
Dispatch Job
 ↓
Queue
 ↓
Worker
 ↓
Proses Berat

Dengan pola tersebut Scheduler hanya bertugas memicu pekerjaan.

Scheduler dan Redis

Jika aplikasi sudah menggunakan Redis untuk Queue, Redis juga dapat membantu beberapa fitur scheduling yang membutuhkan cache/lock.

Namun pastikan konfigurasi Redis benar.

Misalnya:

REDIS_HOST=127.0.0.1
REDIS_PORT=6379

Jika menggunakan withoutOverlapping() atau onOneServer(), konfigurasi cache yang digunakan aplikasi harus mendukung mekanisme lock yang diperlukan.

Scheduler Tidak Berjalan Setelah Deploy

Jika Scheduler bekerja di lokal tetapi tidak di production, periksa:

Cron
PHP path
Project path
Environment
Timezone
Permission
Configuration cache

Mulai dengan:

php artisan schedule:list

Kemudian:

php artisan schedule:run

Jika manual berhasil, kemungkinan masalah berada pada Cron atau environment server.

Masalah Cron Menggunakan PHP yang Berbeda

Misalnya terminal:

php -v

menghasilkan:

PHP 8.3

tetapi Cron menjalankan:

PHP 8.1

Task bisa gagal karena dependency atau syntax yang tidak kompatibel.

Gunakan absolute path:

* * * * * cd /var/www/example.com && /usr/bin/php artisan schedule:run >> /dev/null 2>&1

Pastikan /usr/bin/php memang versi yang benar.

Masalah Permission pada Cron

Cron dapat berjalan menggunakan user yang berbeda dari PHP-FPM.

Misalnya:

Cron
 ↓
www-data

tetapi file project dimiliki:

deploy

Jika Scheduler menjalankan Command yang membutuhkan write access, dapat muncul:

Permission denied

Periksa user Cron:

whoami

dan permission directory Laravel.

Periksa Log Laravel

Jika task berjalan tetapi Command mengalami error:

tail -f storage/logs/laravel.log

Ini penting untuk membedakan:

Scheduler tidak dipanggil

dengan:

Scheduler dipanggil tetapi task error

Cara Debugging yang Sistematis

Jika task tidak berjalan, gunakan urutan:

1. Task terdaftar?
       ↓
   schedule:list

2. Scheduler bisa berjalan?
       ↓
   schedule:run

3. Command/Job bisa berjalan?
       ↓
   Jalankan manual

4. Cron aktif?
       ↓
   systemctl status cron

5. Cron entry ada?
       ↓
   crontab -l

6. PHP path benar?
       ↓
   which php

7. Timezone benar?
       ↓
   Laravel config

8. Permission benar?
       ↓
   storage/bootstrap/cache

Urutan ini membantu mempersempit sumber masalah tanpa mengubah banyak konfigurasi sekaligus.

Checklist Laravel Task Scheduling di Ubuntu

Untuk production, checklist sederhananya:

[ ] Task sudah dibuat
[ ] Task muncul di schedule:list
[ ] Command/Job berhasil dijalankan manual
[ ] Laravel configuration benar
[ ] Timezone sesuai
[ ] Cron terinstall
[ ] Cron service aktif
[ ] Crontab sudah dikonfigurasi
[ ] Absolute path PHP benar
[ ] Project path benar
[ ] Permission benar
[ ] Queue Worker aktif jika menggunakan Job
[ ] Log dapat diperiksa
[ ] Overlapping dipertimbangkan

Contoh Setup Lengkap

Misalnya kita memiliki Command:

php artisan cleanup:temporary-data

Scheduler:

use Illuminate\Support\Facades\Schedule;

Schedule::command('cleanup:temporary-data')
    ->dailyAt('02:00')
    ->withoutOverlapping();

Cron Ubuntu:

* * * * * cd /var/www/example.com && /usr/bin/php artisan schedule:run >> /dev/null 2>&1

Alurnya:

Setiap menit
     ↓
Ubuntu Cron
     ↓
php artisan schedule:run
     ↓
Laravel mengecek jadwal
     ↓
Apakah pukul 02:00?
     ↓
Ya
     ↓
cleanup:temporary-data

Jika pukul 10:00:

Cron
 ↓
schedule:run
 ↓
Bukan waktu task
 ↓
Tidak menjalankan cleanup

Contoh Scheduler dengan Queue

Untuk proses yang lebih berat:

Schedule::job(new GenerateDailyReport)
    ->dailyAt('08:00')
    ->withoutOverlapping();

Kemudian:

08:00
 ↓
Scheduler
 ↓
GenerateDailyReport
 ↓
Redis
 ↓
Queue Worker
 ↓
Generate Report

Supervisor menjaga Queue Worker:

Supervisor
 ↓
queue:work

Sehingga ketiga komponen bekerja bersama:

Cron
 ↓
Laravel Scheduler
 ↓
Redis Queue
 ↓
Supervisor
 ↓
Queue Worker

Kesimpulan

Laravel Task Scheduling digunakan untuk menjalankan Command, Job, Closure, atau task lain secara otomatis berdasarkan jadwal.

Konsep utamanya sederhana:

Cron
 ↓
Laravel Scheduler
 ↓
Task

Pada aplikasi yang menggunakan Queue:

Cron
 ↓
Scheduler
 ↓
Queue Job
 ↓
Redis
 ↓
Queue Worker

Untuk membuat Scheduler berjalan di Ubuntu, konfigurasi yang paling umum adalah:

* * * * * cd /var/www/example.com && /usr/bin/php artisan schedule:run >> /dev/null 2>&1

Kemudian jadwal didefinisikan di Laravel, misalnya:

Schedule::command('cleanup:temporary-data')
    ->dailyAt('02:00');

Untuk task yang membutuhkan waktu lama, pertimbangkan menggunakan:

Schedule::job(new GenerateDailyReport)
    ->dailyAt('08:00')
    ->withoutOverlapping();

Dengan pola tersebut, Cron bertugas memicu Scheduler, Scheduler menentukan kapan task dijalankan, sedangkan Queue Worker menangani pekerjaan background yang berat.

Untuk production, jangan lupa memperhatikan timezone, permission, PHP path, Cron service, Queue Worker, Redis, dan logging. Hal-hal tersebut merupakan penyebab umum ketika Laravel Scheduler terlihat sudah dikonfigurasi tetapi task sebenarnya tidak pernah berjalan.