Instead of maintaining many crontab lines, Laravel lets you define all scheduled tasks in code — reports, cleanups, backups, reminder emails — and run them from a single cron entry that calls the scheduler every minute.

1. Define tasks

In Laravel 11+, tasks live in routes/console.php (older versions: app/Console/Kernel.php):

use Illuminate\Support\Facades\Schedule;

Schedule::command('reports:daily')->dailyAt('06:00')->timezone('Europe/London');

Schedule::command('cache:prune-stale-tags')->hourly();

Schedule::job(new \App\Jobs\SyncInventory)->everyFifteenMinutes();

Schedule::call(fn () => \App\Models\Session::where('expires_at', '<', now())->delete())
    ->daily()
    ->name('purge-sessions');

Schedule::command('backup:run')->dailyAt('02:30')
    ->withoutOverlapping()
    ->onOneServer()
    ->emailOutputOnFailure('[email protected]');

Useful frequency methods: everyMinute(), everyFiveMinutes(), hourlyAt(17), daily(), dailyAt('13:00'), weekdays(), weekly(), monthlyOn(1, '04:00'), cron('15 3 * * 1').

2. Add the cron entry on the server

As the user that owns the application (not root):

sudo crontab -u deploy -e
* * * * * cd /var/www/laravel && php artisan schedule:run >> /dev/null 2>&1

Every minute, schedule:run checks which tasks are due and runs them. Use the full PHP path (command -v php) if cron’s PATH doesn’t find it, or a specific version (/usr/bin/php8.3) on servers with several PHP versions. See the crontab guide.

Alternative: schedule:work

php artisan schedule:work runs the scheduler in the foreground, checking every minute — handy in containers where cron isn’t available. Supervise it with Supervisor or systemd like a queue worker.

Alternative: systemd timer

# /etc/systemd/system/laravel-schedule.service
[Service]
Type=oneshot
User=deploy
WorkingDirectory=/var/www/laravel
ExecStart=/usr/bin/php artisan schedule:run

# /etc/systemd/system/laravel-schedule.timer
[Timer]
OnCalendar=*-*-* *:*:00
AccuracySec=1s
[Install]
WantedBy=timers.target

sudo systemctl enable --now laravel-schedule.timer. Output goes to the journal. See systemd timers.

3. Check what’s scheduled

php artisan schedule:list
php artisan schedule:test          # pick a task and run it now
php artisan schedule:run -v        # run due tasks with output

schedule:list shows each task’s expression and next run time.

4. Prevent overlaps and duplicates

  • withoutOverlapping() — skip a run if the previous one is still going (uses a cache lock; set an expiry in minutes as argument if tasks may die without releasing it).
  • onOneServer() — with several app servers sharing a cache (Redis/Memcached/database), only one server runs the task. Without it, every server with the cron entry runs every task.
  • runInBackground() — start the task and move on, so long tasks don’t delay others due at the same minute.

5. Output and monitoring

Schedule::command('reports:daily')
    ->daily()
    ->appendOutputTo(storage_path('logs/reports.log'))
    ->onFailure(fn () => logger()->error('Daily report failed'))
    ->pingOnSuccess('https://hc-ping.com/your-uuid');

pingOnSuccess/pingBefore integrate with heartbeat monitors (Healthchecks.io, Uptime Kuma push monitors), so you’re alerted when a task doesn’t run — the most common silent failure.

6. Time zones

Tasks use the app’s timezone (config/app.php) unless you call ->timezone(). Daylight saving changes can skip or repeat tasks scheduled between 1 and 3 a.m. in affected zones — prefer UTC for the app and schedule in UTC.

Troubleshooting missed runs

  1. Is the cron entry present for the right user? sudo crontab -u deploy -l
  2. Does cron run it? grep CRON /var/log/syslog | tail (or journalctl -u cron).
  3. Run it manually: cd /var/www/laravel && php artisan schedule:run -v.
  4. Is the right PHP version used, with the needed extensions?
  5. Stale overlap lock? Clear with php artisan schedule:clear-cache.
  6. Config cached with an old schedule? Run php artisan optimize:clear after deploys (then re-cache).

Related: Laravel queues with Supervisor and deploying Laravel.

  • Laravel
  • Cron
  • PHP