Skip to content

Laravel 12 Task Scheduling with Cron Jobs

Learn how to set up Laravel 12 task scheduling with cron jobs. Step-by-step guide to automate commands, schedule tasks, and boost app efficiency in Laravel.

Dasun Kalupahana 2 min read 1.7K views 0 comments

Task scheduling is a fundamental feature of modern web applications that provides numerous benefits for automation, maintenance, and system efficiency. Let’s explore the key reasons why you should use task scheduling in Laravel applications.

Automation
  • Runs repetitive tasks (emails, reports, cleanups) automatically without manual intervention.
Performance Optimization
  • Executes heavy tasks (like backups) during off-peak hours to avoid slowing down users.
Reliability
  • Ensures critical tasks (e.g., daily DB backups) run on time, every time, eliminating human error.
Maintenance
  • Automates system health tasks (cache clearing, log rotation) to keep apps running smoothly.
Queue Management
  • Controls when background jobs (e.g., order processing) run for better resource usage.
Timezone Handling
  • Schedules tasks based on business hours or user locations (e.g., “Send at 9 AM local time”).
Error Handling
  • Auto-retries failed tasks and notifies developers via logs/emails.
Simplicity
  • Replaces complex cron syntax with readable Laravel methods like ->daily() or ->everyFiveMinutes().
 

Step-by-Step Implementation


Step 1: Set Up the Cron Entry on Your Server

First, you need to add a cron entry that runs the Laravel schedule. On your server, run:

crontab -e

Add this line (replace /path-to-your-project with your actual project path):

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

What This Does

1. * * * * *

  • Runs the command every minute (cron syntax for “always”).
  • You can use Cron Guru, a tool that simplifies the creation and understanding of cron expressions used for scheduling tasks in Unix-like systems.

2. cd /path-to-your-project

  • Navigates to your Laravel root directory (where artisan lives).
  • Replace with your actual path (e.g., /var/www/myapp).

3. php artisan schedule:run

  • Laravel’s scheduler — checks routes/console.php and runs any due tasks.

4. >> /dev/null 2>&1

  • Silences output (no spam in server logs).
  • >> /dev/null hides normal output.
  • 2>&1 redirects errors to the same void.
Step 2: Define Your Scheduled Tasks

All scheduled tasks are defined in the routes/console.php file. Here’s a complete example with different types of scheduled tasks:

<?php

use App\Jobs\SendDailyReports;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Schedule;

// Example 1: Run a command daily at midnight
Schedule::command('inspire')->daily();

// Example 2: Run a custom command every hour
Schedule::command('orders:process')->hourly();

// Example 3: Run a closure every minute
Schedule::call(function () {
    Log::info('This task runs every minute');
})->everyMinute();

// Example 4: Run a job on weekdays at 8:00 AM
Schedule::job(new SendDailyReports)->weekdays()->at('08:00');

// Example 5: Run a command with specific timezone
Schedule::command('notifications:send')
    ->timezone('America/New_York')
    ->dailyAt('13:00');

// Example 6: Run task between specific hours
Schedule::command('backup:run')
    ->everyThirtyMinutes()
    ->between('8:00', '17:00');

// Example 7: Run task only when environment is production
Schedule::command('queue:work --stop-when-empty')
    ->everyFiveMinutes()
    ->environments(['production']);

// Example 8: The exec method may be used to issue a command to the operating system:
Schedule::exec('node /home/forge/script.js')->daily();

You can find all available schedule frequency options in the Laravel Scheduling Documentation

Step 3: Create a Custom Command

If you want to schedule a custom command, first create it:

php artisan make:command ProcessOrders --command=orders:process

Then define the command logic in app/Console/Commands/ProcessOrders.php:

<?php

namespace App\Console\Commands;

use App\Models\Order;
use Exception;
use Illuminate\Console\Command;

class ProcessOrders extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'orders:process';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'Process pending orders';

    /**
     * Execute the console command.
     */
    public function handle(): void
    {
        try {

            $this->info("Process started.");
            $orders = Order::where('status', 'pending')->get();

            foreach ($orders as $order) {
                // Process each order
                $order->update(['status' => 'processed']);
                $this->info("Processed order #{$order->id}.");
            }

            $this->info('All pending orders processed successfully.');
            $this->info('Process ended.');
        } catch (Exception $exception) {
            $this->error($exception->getMessage());
        }
    }
}

Define your command in routes/console.phpfile.

// Option 1: Using Command Signature (String)
Schedule::command('orders:process')->daily();
// Option 2: Using Command Class
Schedule::command(ProcessOrders::class)->daily();
Step 4: Test Your Scheduled Tasks

Before relying on the cron, test your tasks:

1. Test individual commands:

php artisan orders:process

2. Test the scheduler (runs all due tasks):

php artisan schedule:run

3. For debugging, add output:

$schedule->command('orders:process')
         ->hourly()
         ->sendOutputTo(storage_path('logs/orders.log'));

Advanced Scheduling Options

Task Hooks

You can add code to run before and after a task:

$schedule->command('orders:process')
         ->daily()
         ->before(function () {
             Log::info('About to process orders');
         })
         ->after(function () {
             Log::info('Finished processing orders');
         });
Prevent Task Overlaps

Prevent a task from running if the previous instance is still running:

$schedule->command('emails:send')
         ->everyMinute()
         ->withoutOverlapping();
Run Tasks on One Server

If your app runs on multiple servers, ensure a task runs on only one server:

$schedule->command('report:generate')
         ->daily()
         ->onOneServer();

Monitoring Scheduled Tasks

View scheduled tasks:

php artisan schedule:list

Log all scheduler activity:

public function handle(): void
{
  try {
        Log::info('Process started.');
        $orders = Order::where('status', 'pending')->get();

        foreach ($orders as $order) {
           // Process each order
           $order->update(['status' => 'processed']);
           Log::info("Processed order #{$order->id}.");
        }

        Log::info('All pending orders processed successfully.');
        Log::info('Process ended.');
      } catch (Exception $exception) {
        Log::error($exception->getMessage());
      }
}

Best Practices

  1. Keep task durations short: Long-running tasks should be queued.
  2. Use meaningful task names: Makes logging and debugging easier.
  3. Handle failures gracefully: Use try-catch blocks in your commands.
  4. Monitor task execution: Set up alerts for failed tasks.
  5. Document your tasks: Add comments explaining what each scheduled task does.

If you found this helpful, feel free to share or drop a comment. Happy coding with Laravel! 🧱✨

Free resources for this topic

Code snippets and fixes for this topic

Get one practical tip every week

New tutorials, fixes and free cheat sheets from DEV Talk, straight to your inbox. No spam, unsubscribe in one click.

Free download: Laravel interview questions (PDF)

Have a question about this post?

Ask the community: other developers and the author can answer.

Ask the community

Get notified about new articles

One click, no email needed. Turn it off anytime with the bell at the top.

Get new articles on your iPhone

Add DEV Talk to your Home Screen, open it, then tap the bell.

Rate this post
5.0
Share

Enjoying the content?

If this article helped you, you can support the author with a coffee. It keeps new posts coming.

Buy me a coffee (opens in a new tab)

Comments 0

Be kind. Comments with links are reviewed before they appear.

No comments yet

Be the first to share your thoughts.

Get new articles in your inbox

Practical tutorials and deep dives, about once a week. No spam, unsubscribe anytime.

Privacy policy

Add DEV Talk to your Home Screen

  1. 1 Tap the Share button in Safari's toolbar.
  2. 2 Scroll down and tap Add to Home Screen.
  3. 3 Tap Add. Open it from the Home Screen to read like an app and to turn on notifications with the bell.

We use cookies to improve your experience and analyze traffic. By continuing, you agree to our Privacy Policy.