Setting Up Automated Database Backups in Laravel with Task Scheduling

Backups are one of those things you only think about after something goes wrong. A corrupted migration, an accidental DELETE without a WHERE clause, a compromised server — any of these can mean permanent data loss if you don’t have a reliable backup strategy in place.

This tutorial walks through setting up automated database backups in a Laravel application using the Calm Backup package.

Installing the Package

composer require calmbackup/backup

Then run the Laravel-specific install command:

php artisan backup:install

This publishes a configuration file to config/backup.php, prompts you to connect your Calm Backup account, and generates a local encryption key for AES-256-GCM encryption. Your key never leaves your server — Calm Backup operates on a zero-knowledge model. The command also auto-detects your database driver (MySQL, PostgreSQL, or SQLite).

Running Your First Backup

php artisan backup:run

This dumps your database, encrypts it locally, uploads the encrypted file, and records a checksum for integrity verification. The backup appears in your dashboard within seconds.

Automating with Laravel’s Task Scheduler

Laravel 11+ (routes/console.php)

use Illuminate\Support\Facades\Schedule;

Schedule::command('backup:run')->daily();

Laravel 10 and earlier (app/Console/Kernel.php)

protected function schedule(Schedule $schedule): void
{
$schedule->command('backup:run')->daily();
}

Scheduling Options

Daily at midnight: ->daily()

Daily at a specific time: ->dailyAt('02:00')

Twice per day: ->twiceDaily(1, 13)

Every hour: ->hourly()

Every six hours: ->everySixHours()

Weekly at a specific time: ->weekly()->at('03:00')

For most production apps, a daily backup at an off-peak hour works well:

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

For high-traffic applications, hourly backups ensure you never lose more than an hour of data:

Schedule::command('backup:run')->hourly();

You can also restrict to production only:

Schedule::command('backup:run')
->when(fn () => app()->environment('production'))
->hourly();

Setting Up the Cron Entry

Laravel’s scheduler needs a single cron entry to run every minute:

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

Edit the crontab for the web server user:

crontab -e -u www-data

Verifying Backups Are Running

The Dashboard

Your Calm Backup dashboard shows a full history of backup runs with timestamps, file sizes, and checksum verification status.

Missed Backup Alerts

Calm Backup monitors your expected schedule and sends an alert if a backup doesn’t arrive within the expected window. If your cron stops running or a deployment misconfigures something, you’ll know immediately.

Running on Deployment Platforms

Laravel Forge

Navigate to your server’s Scheduler tab and add php artisan schedule:run with frequency set to Every Minute. Forge handles the crontab for you.

Laravel Vapor

Define the schedule in vapor.yml:

scheduler:
- command: "php artisan schedule:run"
frequency: "* * * * *"

Other Platforms (Heroku, Railway, Render)

Configure the platform to run php artisan schedule:run every minute. Make sure credentials are set as environment variables.

Restoring from a Backup

php artisan backup:restore

This automatically downloads the encrypted backup, decrypts it locally using your stored key, and imports it into your database. The entire process is handled in a single command — no manual downloads or decryption steps.

For non-interactive environments:

php artisan backup:restore --backup=<backup-id>

Wrapping Up

With the calmbackup/backup package and a single scheduler entry, you get automated, encrypted, verified database backups. The zero-knowledge encryption keeps your data private, and missed backup alerts mean you’ll know immediately if something stops working. The full setup takes about ten minutes.