We all know how important database backups are. Even if functionalities like Multi AZ support, multiple replicas, it's importance can't be more emphasised.

Ruby has a handy wrapper to automate this.

Setup Requirements:

  1. A linux server (proper disk space should be there, atleast the size of your database)
  2. Ruby installation. (rvm/rbenv can be used)
  3. Slack/Flock/Mattermost/SMTP (*not required, but good to have)
  4. Place where to store the backup. I personally prefer S3. It can be local, FTP or anything of that sort.


  1. Install backup gem. As I write this post, 4.3.0 is the latest release out there. You can install the same with gem install backup

    However, there are certain problems on some systems with the installation. If you face any error, try installing the nextrc candidate gem install backup -v5.0.0.beta.1
  2. Backup gem provides a cli utility for ease. Generate the config file by running this task: backup generate:model --trigger producion_backup --archives --storages='s3' --databases='postgresql' --compressor='gzip' . The flags are self explanatory IMO.
  3. Open up the generated file:
    vim ~/Backup/models/production_backup.rb
  4. Replace, and tweak the needed items:
# encoding: utf-8

Model.new(:producion_backup, 'Description for producion_backup') do
  archive :configs do |archive|
    archive.add "/home/ubuntu/projects/api/shared/config/"
    archive.add '/etc/nginx/'

  database PostgreSQL do |db|
    db.name               = "db_name"
    db.username           = "db_username"
    db.password           = "db_password"
    db.host               = "db_url.ap-south-1.rds.amazonaws.com" # or localhost, or anyother hosted service url
    db.port               = 5432 # or any other port that you might have

  # Keep 4 monthly backups
  #      6 weekly
  #      7 daily
  # and  23 daily backups
  time = Time.now
  if time.hour == 0
    if time.day == 1  # first day of the month
      storage_id = :monthly
      keep = 4
    elsif time.sunday?
      storage_id = :weekly
      keep = 7
      storage_id = :daily
      keep = 6
    storage_id = :hourly
    keep = 23

  store_with S3 do |s3|
    # AWS Credentials
    s3.access_key_id     = "AWS_access_key_id"
    s3.secret_access_key = "AWS_secret_access_key"
    s3.region            = "ap-south-1"
    s3.bucket            = "db-backups"
    s3.path              = "/backups/#{storage_id}"
    s3.keep              = keep

  # can use mattermost/Flock or anyother servicee that takes in webhooks.
  notify_by Slack do |slack|
    slack.on_success           = true
    slack.on_failure           = true
    slack.webhook_url          = 'Webhook URL'
    slack.username             = 'Backup bot'
    slack.channel              = 'db-backup-alerts'
    slack.icon_emoji           = ':ice:'

  compress_with Gzip

5. Create a bucket in S3 before running the trigger.

6. Trigger the backup with backup perform --trigger production_backup

7. Verify the backup after it's done and uploaded over to S3.

8. Put up a cron job for automating this, 0 * * * * /bin/bash -l -c 'rvm use 2.6.3 && backup perform --triggert producion_backup'. The job will run every hour.

9. Why the server hard disk needs to be large? Because this gem creates an archive of the tables and other items in local first, and then uploads it.

I hope the article was helpful for you!

Documentation and more tweaking options for Backup gem can be found here.