Every two weeks I send out a newsletter containing lots of interesting stuff for the modern PHP developer. You can expect quick tips, links to interesting tutorials, opinions and packages. Want to learn the cool stuff? Then sign up now!

A modern backup solution for Laravel apps

Today our team released a new major version of laravel-backup. It can backup the files and databases of your application to one or more external filesystems. It uses Laravel’s native cloud filesystem to do this. The package can also notify you via Slack and/or email when something goes wrong with your backups. We’ve also created a dedicated site with full documentation. In this blogpost we want to give you some background of why and how the package was created.


In the Laravel 4 days we ware using Johannes Schickling’s backup package to dump an application’s database and copy it over to S3. Then Laravel 5 came out. Unfortunately Johannes’ package was never updated. So… we had to create a backup package ourselves. Version 1 could simply dump the database. The next major version added functionality to zip specific directories and copy them over to external filesystems.

A lot of other developers found laravel-backup useful. A few weeks ago the package reached 40k downloads and 500 stars on GitHub. We thought this was amazing. It’s our most popular package by far. Creating a popular package was such an awesome experience that our team is now continuously releasing new open source stuff and helping the community.

In January of this year Jack Fruh of the Laravel News Podcast called to talk about the backup backage. You can listen to our conversation in episode 8 of the podcast. At a certain point Jack asks if the package sends out notifications when something goes wrong (it didn’t). That question led us to add monitoring functionality and notifications to version 3. Thanks Jack!

The package was one of the first Spatie packages that was ever released. In the past year we learned a lot, so we definitely could see room for improvement in the old code.

An overview of all functionality in version 3

Version 3 of the package has <bragmode>plenty awesome features</bragmode>. Take a look at the config file to get a quick overview of all functionality. Most options are self-explanatory, but there some comments to make everything very clear.

Taking backups

Most importantly, the package can take backups. That’s probably a good thing considering the package is named laravel-backup. A backup is a zip file that contains the files of your application together with the dumps of one or more databases. The zipfile can be copied over to one or more filesystems.

To take a backup you can run this command: php artisan backup:run. We recommend that you schedule this command using Laravel’s native scheduler.  To take a quick backup of your database you can run php artisan backup:run --only-db. This can be handy in your deployment strategy.

Cleaning up old backups

Over time the amount of backups and the storage needed to keep them will grow. At some point you are going to want to clean up old backups. The package provides an opinionated method to determine which old backups should be deleted. This is how the clean up works:

  • Rule #1: it will never delete the youngest backup regardless of it’s size or age
  • Rule #2: it will keep all backups for the amount of days specified in keepAllBackupsForDays
  • Rule #3: it’ll only keep daily backups for the amount of days specified in keepDailyBackupsForDays for all backups older than those that rule #2 takes care of
  • Rule #4: it’ll only keep weekly backups for the amount of days specified in keepMonthlyBackupsForMonths for all backups older than those that rule #3 takes care of
  • Rule #5: it’ll only keep yearly backups for the amount of years specified in keepYearlyBackupsForYears for all backups older than those that rule #4 takes care of
  • Rule #6: it will delete backups will keep on deleting backups until the used storage is lower than the number specified in deleteOldestBackupsWhenUsingMoreMegabytesThan.

Of course the numbers used in the default configuration can be adjusted to your own liking. This strategy ensures that you have a lot of young backups and a few older ones.

To clean up all backups simply run php artisan backup:clean. We recommend to schedule this command as well.

Monitoring the health of all backups

The package can monitor the health of every application it is installed into. If a backup is unhealty, a notification can be sent to you via mail of Slack, more on that later.

To monitor the backups of your applications we recommend setting up this package in a separate Laravel installation preferably on a separate server. Doing it this way will ensure that the monitoring will still work even if one of the applications you are monitoring is broken.

To get a quick overview of the health all your backups you can run php artisan backup:list. The output of that command will look like this:

output of backup:list

In the screenshot above you see a quick test I whipped up that uses a well configured local destination and S3 destination with some faulty credentials.

Sending notifications

The package can let you know that your backups are (not) ok. It can notify you via mail and or Slack when an (un)healthy backup is found or when a backup or clean was (un)successful.

This is what a Slack notification looks like:

Some other tidbits

Besides all that functionality, there are lots of other tiny features that you can make use of:

Show me the code!

We made great efforts to create readable code. Take a look at this function from the BackupJob-class which takes care of creating backups:

public function run()
    try {
        $this->temporaryDirectory = TemporaryDirectory::create();

        $zip = $this->createZipContainingAllFilesToBeBackedUp();



    } catch (Exception $exception) {
        event(new BackupHasFailed($exception));

This is the code that creates the zip-file:

protected function createZipContainingAllFilesToBeBackedUp()
    $zip = Zip::create($this->temporaryDirectory->getPath(date('Y-m-d-His').'.zip'));



    event(new BackupZipWasCreated($zip));

    return $zip;

By browsing the code you can easily work out the inner workings of the package. Reading other people’s code is always a good way to learn new stuff. We hope you pick up a few things by reading ours.

The documentation site

The previous version of the backup had, like most packages, a simple readme on GitHub to guide users. A simple readme wasn’t going to cut it anymore. That’s why we created a small documentation site.

It’s built with Laravel 5.2. The source code of the entire application is available on GitHub.  If you have an idea to improve the docs or see an error, submit a PR to that repo. Changes to the repo are auto deployed to a DigitalOcean droplet that runs the documentation site.

The views of the application are not simple blade views, but Markdown files. All requests are routed to the PageController which is responsible for converting the markdown file to html and displaying it.

The markdown is parsed by the League’s CommonMark package in combination with our own yaml-front-matter parser. The menu of the site is rendered by a new package called laravel-menu, of which we will release a stable first release soon. It’ll feature a very easy to use syntax and a handy way to mark menu items as being active.

On the usage of PHP 5

Some of you might already know that we decided to, from this point on, only release PHP 7 packages.  One of our arguments to go PHP 7 only was that we primarily create packages for our own projects and don’t really care if a package is popular or not (though on a personal level having a package becoming popular feels awesome). When we started out coding up the new version of laravel-backup the package was PHP 7 only.

But then DigitalOcean lost one of our servers. From one moment to the next it ceased to exist. Poof! This event changed our stance. We decided that the backup package should be available for as many people as possible. That’s why we ensured that package is compatible with PHP 5. We do foresee however that, by the end of this year, we’ll release a PHP 7 only version.


We see our package as a good solution for small to medium sized projects. But of course there are plenty of quality alternatives.

Backup Manager, by Mitchell van Wijngaarden and Shawn McCool, is a framework agnostic solution. It can backup and restore files and databases to a myriad of filesystems.

BackupPC is an enterprise grade backup system. It works by SSH’ing into your servers and rsync’ing all files to it’s own disk. It’s a little bit harder to configure, you’ll find installation instructions on the DigitalOcean site. Another enterprise grade solution is Bakula.

If you’re in the market for a SaaS solution, take a look at Ottomatik.io. This service isn’t free, but in exchange for your hard earner dollars or euros you get a very good-looking UI to configure backups and restores.

Closing notes

You’ve almost reached the end of this post. If you made it this far we hope you’ll try out the package and let us know what you think of it.

It’s been fun creating v3. Hopefully it’ll become as successful as the previous version. Creating this package is a good reminder that the biggest effort in creating a package doesn’t lie in creating working code, but refactoring it for maximum readability, creating tests, writing and layouting documentation and… this introductory blog post. Probably we’ll have to spend some time answering questions and fixing issues. But that’s all worth it.

We’ll leave you with two links:

Do you like the this package? Or have a suggestion on how to make it better? Let me know in the comments below.

Freek Van der Herten is a partner and developer at Spatie, an Antwerp based company that specializes in creating web apps with Laravel. After hours he writes about modern PHP and Laravel on this blog. When not coding he’s probably rehearsing with his kraut rock band.
  • marcusamoore

    Awesome update! I like the health monitoring feature.

    I’ve started to move projects over to PHP7 but I’m glad you’re keeping PHP 5 an option for the time being for the same reasons you noted.

  • It’s cool, but I don’t feel there is anything compelling in making my app back itself up…

    What is the use-case for this?

    Unless you live-edit your apps, you should only need the backup the data from the DB & file-storage, which rsync, openssh, tar & mysql client kinda solve for you.

    • There are a million ways to back up an app. I think there’s no single “best” way to do it. It all depends on the size of the projects, your company and the profiles of the people working on the project.

      I believe this package is best used for small to medium projects for small teams without a dedicated ops guy.

  • Rohith Meethal

    Thanks for the awesome package !
    I would love to have an option to restore the backups to the current system, may be a backup discovery system, that can automatically look for backups in backup location and then we can restore it (For server migrations) . I know I am asking too much !!

    I really appreciate time and effort you guys have put on making all these open source laravel packages.

    • Hi, thanks for the kind words on our packages.

      A restore feature isn’t planned. We primarily build these packages for our own projects. When something goes wrong I’d rather fix things manually. In the size of projects we work on (small / medium) that’s perfectly doable. And it’s not like things are crashing and burning everyday. 🙂

      But I can see value in the package having this feature. If it doesn’t take much code, maybe I would accept it as a PR

  • Pingback: Laravel News Podcast #12 - Laravel News()

  • Pingback: March 2016 Review | Andre Madarang()

  • jzpeepz

    I love this package. It works great! Notifications via Slack are just the icing on the cake.

    Have you considered a way to configure multiple backups? Each having their own name, file paths, excluded paths, and databases. This would allow folks (like me) to backup and individually monitor multiple applications (even legacy) from a single Laravel install on that server. It would be very cool, but I understand it may not suit your use case.

    • Well, you can already make your monitor check backups for multiple applications. The `monitorBackups` key in the config file takes an array. You can specify multiple jobs there.

      In a next major version of the package (no concrete plans yet, but I guess it’ll be something for 2017), I’ll make making multiple backup jobs easier.

  • Pingback: Checklist: 8 Things to Do When Launching Laravel Project LIVE - Laravel Daily()

  • Joseph

    Any way to add gzip compression to the sql file so it is easy to restore if needed?