Laravel Backup v10: serializable events, resilient multi-destination backups, and more original

by Freek Van der Herten – 4 minute read

We just released v10 of laravel-backup, our package that creates backups of your Laravel app. The backup is a zip file containing all files in the directories you specify, along with a dump of your database. You can store it on any of the filesystems Laravel supports, and you can even back up to multiple disks at once.

We originally created this package after DigitalOcean lost one of our servers. That experience taught us the hard way that you should never rely solely on your hosting provider for backups. The package has been actively maintained ever since.

Taking backups

With the package installed, taking a backup is as simple as running:

php artisan backup:run

This creates a zip of your configured files and databases and stores it on your configured disks. You can also back up just the database or just the files:

php artisan backup:run --only-db
php artisan backup:run --only-files

Or target a specific disk:

php artisan backup:run --only-to-disk=s3

In most setups you'll want to schedule this. In your routes/console.php:

use Illuminate\Support\Facades\Schedule;

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

Listing and monitoring backups

To see an overview of all your backups, run:

php artisan backup:list

This shows a table with the backup name, disk, date, and size for each backup.

The package also ships with a monitor that checks whether your backups are healthy. A backup is considered unhealthy when it's too old or when the total backup size exceeds a configured threshold.

php artisan backup:monitor

You'll typically schedule the monitor to run daily:

Schedule::command('backup:monitor')->daily()->at('03:00');

When the monitor detects a problem, it fires an event that triggers notifications. Out of the box the package supports mail, Slack, Discord, and (new in v10) a generic webhook channel.

Cleaning up old backups

Over time backups pile up. The package includes a cleanup command that removes old backups based on a configurable retention strategy:

php artisan backup:clean

The default strategy keeps all backups for a certain number of days, then keeps one daily backup, then one weekly backup, and so on. It will never delete the most recent backup. You'll want to schedule this alongside your backup command:

Schedule::command('backup:clean')->daily()->at('02:00');

What's new in v10

v10 is mostly about addressing long-standing community requests and cleaning up internals.

The biggest change is that all events now carry primitive data (string $diskName, string $backupName) instead of BackupDestination objects. This means events can now be used with queued listeners, which was previously impossible because those objects weren't serializable. If you have existing listeners, you'll need to update them to use $event->diskName instead of $event->backupDestination->diskName().

Events and notifications are now decoupled. Events always fire, even when --disable-notifications is used. This fixes an issue where BackupWasSuccessful never fired when notifications were disabled, which also broke encryption since it depends on the BackupZipWasCreated event.

There's a new continue_on_failure config option for multi-destination backups. When enabled, a failure on one destination won't abort the entire backup. It fires a failure event for that destination and continues with the rest.

Other additions include a verify_backup config option that validates the zip archive after creation, a generic webhook notification channel for Mattermost/Teams/custom integrations, new command options (--filename-suffix, --exclude, --destination-path), and improved health checks that now report all failures instead of stopping at the first one.

On the internals side, the ConsoleOutput singleton has been replaced by a backupLogger() helper, encryption config now uses a proper enum, and storage/framework is excluded from backups by default.

The full list of breaking changes and migration instructions can be found in the upgrade guide.

In closing

You can find the complete documentation at spatie.be/docs/laravel-backup and the source code on GitHub.

This is one of the many packages we've created at Spatie. If you want to support our open source work, consider picking up one of our paid products.

Join 9,500+ smart developers

Get my monthly newsletter with what I learn from running Spatie, building Oh Dear, and maintaining 300+ open source packages. Practical takes on Laravel, PHP, and AI that you can actually use.

"Always fresh, useful tips and articles. Carefully selected community content. My favorite newsletter, which I look forward to every time."

Bert De Swaef — Developer at Vulpo & Youtuber at Code with Burt

No spam. Unsubscribe anytime. You can also follow me on X.

Found something interesting to share? Submit a link to the community section.