Laravel Cron Jobs Explained with Real Examples

Learn how Laravel cron jobs work with real-world examples. Automate tasks, schedule commands, and manage background jobs efficiently in Laravel.

Monish Roy
Monish Roy
Published on April 15, 2026

Introduction to Cron Jobs in Laravel

In modern web applications, automation is essential. Whether it's sending daily newsletters, cleaning up expired sessions, generating reports, or syncing data with external APIs, repetitive tasks need to run without manual intervention.

Traditionally, developers rely on system-level cron jobs to execute PHP scripts at specific intervals. However, Laravel offers a much more elegant and developer-friendly solution: the Task Scheduler.

Instead of writing multiple cryptic cron entries on the server, Laravel lets you define all your scheduled tasks in PHP code within a single file. You only need one cron job on the server that calls php artisan schedule:run every minute, and Laravel handles the rest.

This approach is cleaner, version-controlled, testable, and integrates seamlessly with Laravel's ecosystem (queues, notifications, logging, etc.). In this comprehensive guide, we'll explore how Laravel cron jobs work, how to set them up, and walk through several practical real-world examples.

By the end, you'll be able to confidently automate any recurring task in your Laravel application.

What Are Cron Jobs?

A cron job is a time-based job scheduler in Unix-like operating systems. The name comes from chronos (Greek for time). It allows you to run commands or scripts automatically at specified intervals — every minute, hourly, daily, weekly, or at custom times.

The traditional crontab syntax looks like this:

* * * * * php /path/to/artisan some:command

Each asterisk represents minute, hour, day, month, and day-of-week. Managing many such lines becomes messy, especially when different commands need different schedules.

Laravel abstracts this complexity away with its fluent, readable API.

Laravel's Task Scheduler: How It Works

Laravel's scheduler is built on top of the Symfony Process component and integrates with the Artisan command system. All scheduling logic lives in app/Console/Kernel.php inside the schedule() method.

The only requirement on the server is a single cron entry:

* * * * * cd /path/to/your/project && php artisan schedule:run >> /dev/null 2>&1

Every minute, Laravel checks the defined schedule and runs any task whose frequency condition is met. If a task is not due, nothing happens — no overhead.

This design makes your scheduling logic part of your codebase, allowing version control, code reviews, and easy deployment.

Setting Up the Laravel Task Scheduler

Laravel comes with the scheduler out of the box (since version 5.3). No extra installation is required.

Step 1: Add the Server Cron Entry

Log into your server (usually via SSH) and run crontab -e to edit the crontab. Add this line (replace the path):

* * * * * cd /var/www/your-app && php artisan schedule:run >> /dev/null 2>&1

Step 2: Define Tasks in Kernel.php

Open app/Console/Kernel.php. You'll see the schedule() method:

protected function schedule(Schedule $schedule)
{
    // Your scheduled tasks go here
}

Step 3: Testing Locally

To test without waiting, run:

php artisan schedule:work

This runs in the foreground and executes due tasks immediately, printing feedback.

Alternatively, use php artisan schedule:list to view all registered tasks and their next run times.

Defining Scheduled Tasks

You can schedule Artisan commands, closures, shell commands, or queued jobs.

Scheduling Artisan Commands

The most common approach:

$schedule->command('emails:send-daily-newsletter')
         ->daily()
         ->at('08:00')
         ->timezone('Asia/Dhaka');

Scheduling Closures

For quick one-off logic:

$schedule->call(function () {
    DB::table('recent_users')->delete();
})->daily();

Scheduling Shell Commands

$schedule->exec('node /path/to/script.js')->weekly();

Scheduling Queued Jobs

$schedule->job(new ProcessPodcast)->hourly();

Available Frequency Options

Laravel provides a fluent chainable API with dozens of methods. Here are the most useful ones:

Method Description Example
->cron('* * * * *')Custom cron expressionEvery minute
->everyMinute()Every minute
->everyFiveMinutes()Every 5 minutes
->hourly()Top of every hour
->hourlyAt(15)Every hour at 15 minutes past
->daily()Midnight every day
->dailyAt('13:00')Every day at 13:00
->twiceDaily(1, 13)At 1 AM and 1 PM
->weekly()Sunday at 00:00
->monthly()First day of month at 00:00
->weekdays()Every weekday at 00:00
->mondays()->at('08:30')Every Monday at 08:30

You can chain constraints like ->when(), ->skip(), ->environments(), etc.

Real-World Examples of Laravel Cron Jobs

Example 1: Daily Email Newsletter

First, create an Artisan command:

php artisan make:command SendDailyNewsletter --command=emails:send-daily-newsletter

In the command's handle() method:

public function handle()
{
    $users = User::where('subscribed', true)->get();

    foreach ($users as $user) {
        Mail::to($user)->send(new DailyNewsletter($user));
    }

    $this->info('Daily newsletter sent successfully!');
}

Schedule it:

$schedule->command('emails:send-daily-newsletter')
         ->dailyAt('07:00')
         ->timezone('Asia/Dhaka')
         ->withoutOverlapping()
         ->appendOutputTo(storage_path('logs/newsletter.log'));

Example 2: Clean Up Expired Password Resets

Laravel's default password_resets table accumulates entries. Clean old ones:

$schedule->call(function () {
    DB::table('password_resets')
      ->where('created_at', '<', now()->subDays(7))
      ->delete();
})->dailyAt('02:00');

Example 3: Sync Exchange Rates from External API

Create a command:

php artisan make:command SyncExchangeRates

Inside handle():

$response = Http::get('https://api.exchangerate.host/latest?base=USD');

$rates = $response->json()['rates'];

foreach ($rates as $currency => $rate) {
    CurrencyRate::updateOrCreate(
        ['currency' => $currency],
        ['rate' => $rate, 'updated_at' => now()]
    );
}

Schedule:

$schedule->command('exchange:sync-rates')
         ->everySixHours()
         ->onSuccess(function () {
             Log::info('Exchange rates synced successfully.');
         });

Example 4: Generate Monthly Reports (Queued Job)

Create a queued job:

php artisan make:job GenerateMonthlyReport

Schedule the job directly:

$schedule->job(new GenerateMonthlyReport)
         ->monthlyOn(1, '09:00') // First day of month at 9 AM
         ->withoutOverlapping();

Example 5: Database Backup

Use Laravel's built-in backup (if using spatie/laravel-backup) or mysqldump:

$schedule->exec('mysqldump -u root -psecret database_name > /backups/db_'.date('Y-m-d').'.sql')
         ->dailyAt('03:00');

Advanced Scheduler Features

Preventing Overlaps

Use ->withoutOverlapping() to ensure a task doesn't start if a previous run is still active.

Running on Specific Environments

->environments(['production'])

Pinging URLs on Success/Failure

->pingBefore('https://healthchecks.io/ping/abc123/start')
 ->pingOnSuccess('https://healthchecks.io/ping/abc123')
 ->pingOnFailure('https://healthchecks.io/ping/abc123/fail')

Running in Maintenance Mode

Use ->evenInMaintenanceMode() for critical tasks.

Conditional Execution

->when(function () {
    return Cache::get('reports_enabled', true);
})

Best Practices & Common Issues

  • Use queues for long-running tasks to avoid timeout.
  • Log output with ->appendOutputTo() or ->emailOutputTo().
  • Test thoroughly using schedule:work and Schedule::assertCommandRan() in feature tests.
  • Handle timezones carefully with ->timezone().
  • Monitor with tools like Healthchecks.io or Laravel Horizon.

Common Problems

  • Cron not running → Check server crontab and path.
  • Tasks not firing → Wrong timezone or server time mismatch.
  • Permissions → Ensure the web user can write logs/backups.
  • Shared hosting → Use Laravel's scheduler with external cron services like Easycron or Laravel Forge.

Conclusion

Laravel's Task Scheduler is one of the framework's most powerful yet underrated features. By moving scheduling logic into code, it makes automation reliable, maintainable, and enjoyable.

With just one server cron entry and expressive PHP syntax, you can handle everything from simple cleanups to complex workflows. The real-world examples above should give you a solid starting point for common use cases.

Start small — schedule a daily database cleanup today — and gradually automate more parts of your application. Your future self (and your servers) will thank you!

If you have questions or want to share your own scheduling patterns, drop a comment below.


Frequently Asked Questions

A Cron Job in Laravel is a scheduled task that runs automatically at specified intervals (like every minute, hour, or day). Laravel uses its built-in Task Scheduler to manage cron jobs in a clean and expressive way, instead of writing multiple system-level cron entries.

To set up a Laravel cron job, define your scheduled tasks inside the app/Console/Kernel.php file using the schedule() method. Then, add a single cron entry on your server:

* * * * * php /path-to-your-project/artisan schedule:run >> /dev/null 2>&1

This command runs every minute and executes all scheduled tasks automatically.

Common real-world examples include:

  • Sending scheduled emails (daily reports, reminders)
  • Cleaning up old database records
  • Running backups automatically
  • Syncing data with third-party APIs
  • Generating invoices or reports at specific times 

Laravel Task Scheduler makes cron management easier by allowing all tasks to be defined in one place. It provides expressive methods like daily(), hourly(), and more. It also helps prevent overlapping jobs and offers better logging and control, making your application easier to maintain.

You can test your scheduled tasks manually using the following command:

php artisan schedule:run

For debugging, you can:

  • Use ->logOutput() to store execution logs
  • Check logs in storage/logs/laravel.log
  • Use ->withoutOverlapping() to prevent duplicate runs
  • Run individual commands manually for testing


Leave a Comment

Please to leave a comment.