Skip Navigation
Show nav
Heroku Dev Center Dev Center
  • Get Started
  • Documentation
  • Changelog
  • Search
Heroku Dev Center Dev Center
  • Get Started
    • Node.js
    • Ruby on Rails
    • Ruby
    • Python
    • Java
    • PHP
    • Go
    • Scala
    • Clojure
    • .NET
  • Documentation
  • Changelog
  • More
    Additional Resources
    • Home
    • Elements
    • Products
    • Pricing
    • Careers
    • Help
    • Status
    • Events
    • Podcasts
    • Compliance Center
    Heroku Blog

    Heroku Blog

    Find out what's new with Heroku on our blog.

    Visit Blog
  • Log in or Sign up
View categories

Categories

  • Heroku Architecture
    • Compute (Dynos)
      • Dyno Management
      • Dyno Concepts
      • Dyno Behavior
      • Dyno Reference
      • Dyno Troubleshooting
    • Stacks (operating system images)
    • Networking & DNS
    • Platform Policies
    • Buildpacks
    • Platform Principles
  • Developer Tools
    • AI Tools
    • Command Line
    • Heroku VS Code Extension
  • Deployment
    • Deploying with Git
    • Deploying with Docker
    • Deployment Integrations
  • Continuous Delivery & Integration (Heroku Flow)
    • Continuous Integration
  • Language Support
    • Node.js
      • Node.js Behavior in Heroku
      • Working with Node.js
      • Troubleshooting Node.js Apps
    • Ruby
      • Rails Support
        • Working with Rails
      • Working with Bundler
      • Working with Ruby
      • Ruby Behavior in Heroku
      • Troubleshooting Ruby Apps
    • Python
      • Working with Python
      • Background Jobs in Python
      • Python Behavior in Heroku
      • Working with Django
    • Java
      • Java Behavior in Heroku
      • Working with Java
      • Working with Maven
      • Working with Spring Boot
      • Troubleshooting Java Apps
    • PHP
      • Working with PHP
      • PHP Behavior in Heroku
    • Go
      • Go Dependency Management
    • Scala
    • Clojure
    • .NET
      • Working with .NET
  • Databases & Data Management
    • Heroku Postgres
      • Postgres Basics
      • Postgres Getting Started
      • Postgres Performance
      • Postgres Data Transfer & Preservation
      • Postgres Availability
      • Postgres Special Topics
      • Migrating to Heroku Postgres
    • Heroku Key-Value Store
    • Apache Kafka on Heroku
    • Other Data Stores
  • AI
    • Inference Essentials
    • Inference API
    • Inference Quick Start Guides
    • AI Models
    • Tool Use
    • AI Integrations
    • Vector Database
  • Monitoring & Metrics
    • Logging
  • App Performance
  • Add-ons
    • All Add-ons
  • Collaboration
  • Security
    • App Security
    • Identities & Authentication
      • Single Sign-on (SSO)
    • Private Spaces
      • Infrastructure Networking
    • Compliance
  • Heroku Enterprise
    • Enterprise Accounts
    • Enterprise Teams
  • Patterns & Best Practices
  • Extending Heroku
    • Platform API
    • App Webhooks
    • Heroku Labs
    • Building Add-ons
      • Add-on Development Tasks
      • Add-on APIs
      • Add-on Guidelines & Requirements
    • Building CLI Plugins
    • Developing Buildpacks
    • Dev Center
  • Accounts & Billing
  • Troubleshooting & Support
  • Integrating with Salesforce
    • Heroku AppLink
      • Working with Heroku AppLink
      • Getting Started with Heroku AppLink
      • Heroku AppLink Reference
    • Heroku Connect (Salesforce sync)
      • Heroku Connect Administration
      • Heroku Connect Reference
      • Heroku Connect Troubleshooting
    • Other Salesforce Integrations
  • Databases & Data Management
  • Heroku Postgres
  • Postgres Data Transfer & Preservation
  • Heroku PGBackups

Heroku PGBackups

English — 日本語に切り替える

Table of Contents [expand]

  • Manual Backups
  • Scheduled Backups
  • Downloading Your Backups
  • Check Backup Status and Info
  • Delete a Backup
  • Restore a Backup
  • Direct Database-to-Database Copies
  • Visibility
  • Data Residency

Last updated January 20, 2026

Backups of your data are crucial to any application. Every Heroku Postgres database on the Standard tier or higher comes with an automatic, behind-the-scenes Continuous Protection mechanism that captures physical backups for disaster recovery.

For testing, setting up environments, and migrating data, logical backups offer more portability than physical backups. Heroku Postgres has a PGBackups feature that allows you to take manual and scheduled logical backups. These backups are in a compressed binary format, and are much smaller in size than your database’s actual size on disk.

This article explains how to take manual and scheduled logical backups, show existing backups, restore backups, and transfer data directly between two databases.

Use PGBackups only for moderately loaded databases up to 20 GB. The backup process can time out for databases that are heavily loaded, larger than 20 GB, or databases with many schemas or large objects. See Heroku Postgres Logical Backups for instructions on taking logical backups for databases not suitable for PGBackups.

 

For all production Heroku Postgres plans, use continuous protection for data backup and recovery. Logical backups such as those taken by PGBackups are better suited for use cases requiring data portability.

Manual Backups

Create a Manual Backup

By default, pg:backups operates against your primary database, identified by the DATABASE_URL config var:

$ heroku pg:backups:capture --app example-app
Starting backup of postgresql-octagonal-12345... done

Use Ctrl-C at any time to stop monitoring progress; the backup will continue running.
Use heroku pg:backups:info to check progress.
Stop a running backup with heroku pg:backups:cancel.

Backing up DATABASE to b251... done

The DATABASE_URL config var designates the URL of an app’s primary Heroku Postgres database. You can view the DATABASE_URL config var with the heroku config command.

Alternatively, you can run the pg:backups:capture command and provide the name of the database add-on you want to capture:

USAGE
  $ heroku pg:backups:capture [ADDON]

OPTIONS
  -a, --app=app  (required) app to run command against

EXAMPLE
  $ heroku pg:backups:capture postgresql-sinuous-83720 --app example-app

Capturing a backup adds some load on your database for the duration of the backup. How this impacts your application varies with the size of your database and the nature of the app. Consider taking backups on a follower if there’s a significant impact from running them on the leader. Read more about the performance impact of logical backups.

Create a Manual Backup on Another Database

If you have multiple databases on your application, choose which one to back up by specifying the database name:

$ heroku pg:backups:capture HEROKU_POSTGRESQL_PINK --app example-app
Starting backup of postgresql-transparent-85179... done

Use Ctrl-C at any time to stop monitoring progress; the backup will continue running.
Use heroku pg:backups:info to check progress.
Stop a running backup with heroku pg:backups:cancel.

Backing up PINK to b123... done

Use the flag --verbose to see logs as your backup progresses.

Cancel Manual Backup Creation

To stop a backup, use the cancel command and specify the id of the backup to cancel:

$ heroku pg:backups:cancel b123--app example-app

Cancelling b123... done

Manual Backup Retention Limits

There’s a limit to the number of manual backups you can retain, depending on your database plan.

Plan Backups Retained
Essential-* 5
Standard-* 25
Premium-* 50
Enterprise 50

If you’ve reached this limit and take additional backups, the capture command automatically deletes the oldest manual backup before capturing a new one.

Scheduled Backups

In addition to manually triggered backups, you can schedule regular automatic backups. These backups run daily against the specified database.

Set Up a Backup Schedule

$ heroku pg:backups:schedule DATABASE_URL --at '02:00 America/Los_Angeles' --app example-app

The --at option uses a 24-hour clock to indicate the hour of the day that you want the backup taken. It also accepts a timezone in either the full TZ format (America/Los_Angeles) or the abbreviation (PST), but we recommend using the full TZ format.

You must use the --at option when scheduling a backup. For Windows enclose the --at time and timezone in double-quotes ("), for example, "02:00 America/Los_Angeles".

 

There are no notifications for scheduled backup failures. You must verify your scheduled backup manually.

Backup schedules are associated with your databases’ attachment names, for example, DATABASE_URL and HEROKU_POSTGRESQL_PINK_URL. You can lose the backup schedule if you swap your database or make attachment changes, for example when:

  • You upgrade the database from an Essential-tier plan to a plan in another tier.
  • You switch to a different database by restoring a backup or transferring data into a new database.
  • You update your Heroku Postgres plan with a follower changeover. The schedule from the original database remains associated to the original database. You must create a schedule for the promoted database if it doesn’t exist.

Stop Scheduled Backups

To stop scheduled backups, use unschedule:

$ heroku pg:backups:unschedule DATABASE_URL --app example-app
Unscheduling DATABASE_URL daily backups... done

View Backup Schedules

To view current schedules for your app, use schedules:

$ heroku pg:backups:schedules --app example-app
=== Backup Schedules

DATABASE_URL: daily at 2:00 UTC

Scheduled Backups Retention Limits

Scheduled backups have a different retention policy as compared to manual backups. This policy is also based on the database plan.

Plan Daily Backups Retained Weekly Backups Retained Monthly Backup Retained
Essential-* 7 days 1 week 0 months
Standard-* 7 days 4 weeks 0 months
Premium-* 7 days 8 weeks 12 months
Enterprise 7 days 8 weeks 12 months
  • A daily backup is taken each day at your scheduled time. Daily backups are retained for the last 7 days. That means that 7 backups exist, one for each of the last 7 days.
  • A weekly backup means that one backup is saved over a 7-day period. For example, a Standard-4 database has 4 weeks of weekly backups, one for each of the last 4 weeks.
  • A monthly backup means that 1 backup is saved over the course of a month. For example, a Premium-0 database has 12 monthly backups, one for each of the last 12 months.

We delete backups for deprovisioned add-ons after a short grace period. To retain backups for a deprovisioned database, download your backup within this timeframe and store it in an external data storage service.

Downloading Your Backups

Download via a URL

You can create a publicly accessible backup URL with the pg:backups:url command. This URL is useful for exporting your data outside of Heroku Postgres When the command is specified without a backup id, it returns the latest available backup URL.

$ heroku pg:backups:url b001 --app example-app
https://xfrtu.s3.amazonaws.com/f1a5e48c-1111-2222-3333-c0f8dce21ccb/2026-01-16T17%3A42%3A11Z/1f29f025?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAQ123456%2F20260116%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20260116T175157Z&X-Amz-Expires=3600&X-Amz-SignedHeaders=host&X-Amz-Signature=0b049...

The URL is public but not easily guessable. It expires after 60 minutes.

Download via the Command Line

To download your backup via the command line, you can use the download command:

$ heroku pg:backups:download b123 -a example-app
Getting backup from example-app... done, #123
Downloading latest.dump... ████████████████████████▏  100% 00:00 2.36KB

See our documentation on importing and exporting Heroku Postgres databases with PGBackups for more info.

Check Backup Status and Info

To list your backups and their statuses, run the following:

$ heroku pg:backups --app example-app
=== Backups

 Id    Created at                Status                              Size    Database
 ───── ───────────────────────── ─────────────────────────────────── ─────── ────────────────
b012  2026-01-16 10:21:31 +0000  Running                                     DATABASE
b011  2026-01-15 10:23:52 +0000  Finished 2026-01-15 10:46:25 +0000  1.9GB   DATABASE
b010  2026-01-14 10:25:19 +0000  Finished 2026-01-14 10:49:57 +0000  1.9GB   DATABASE
b004  2026-01-13 10:22:12 +0000  Finished 2026-01-13 10:47:06 +0000  1.9GB   DATABASE


=== Restores

 Id    Started at                Status                              Size   Database
 ───── ───────────────────────── ─────────────────────────────────── ────── ────────
r002  2025-09-08 13:31:56 +0000  Completed 2024-09-09 13:34:36 +0000  1.9GB   IVORY
r001  2024-07-09 02:31:11 +0000  Failed 2024-07-09 02:31:45 +0000    1.7GB   IVORY

To get more details about a given backup, use the info command:

$ heroku pg:backups:info b011 --app example-app
=== Backup b011

Database:         DATABASE
Started at:       2026-01-15 10:23:52 +0000
Finished at:      2026-01-15 10:46:25 +0000
Status:           Completed
Type:             Manual
Original DB Size: 42.57MB
Backup Size:      7.40MB (83% compression)

With the optional --verbose flag, you can also see the backup’s logs. If the backup is still running, the command prints the ongoing logs until the backup finishes or you cancel the command by typing CTRL+C.

PGBackups stores backups in a compressed binary format. The backups include commands to recreate indexes instead of storing the indexes themselves. As a result, backups are much smaller in size than your database’s current size on disk from pg:info.

Delete a Backup

You can manually delete a backup to remove obsolete backups or to make room for new captures. Use the backup ID to specify which backup to remove.

$ heroku pg:backups:delete b101 --app example-app
 ›   Warning: WARNING: Destructive Action
 ›   This command will affect the app example-app

To proceed, type bookish-iri or re-run this command with --confirm example-app: example-app
Deleting backup b101 on ⬢ example-app... done

Restore a Backup

To restore a backup, use the restore command:

$ heroku pg:backups:restore b101 DATABASE_URL --app example-app

This command restores backup id b101 to the specified database URL in the app example-app. Note: you can omit the backup id and the target database to restore the latest backup to DATABASE_URL, otherwise you must provide both the backup id and target database.

You can also restore from a backup on another app (from example-app to example-staging app):

$ heroku pg:backups:restore example-app::b101 DATABASE_URL --app example-staging-app

Or from a publicly accessible URL:

$ heroku pg:backups:restore 'https://s3.amazonaws.com/me/items/mydb.dump' DATABASE_URL -a example-app

To ensure your data is encrypted while in transit, always use an HTTPS URL. Restoring over HTTP is unsupported.

Over time, a database grows on disk due to table bloat and unused index data. As a result, restoring a backup into a new database almost always result in a reduction in overall disk size as reported by pg:info.

You can’t restore a partial backup into an existing database with Heroku PGBackups. Running pg:backups:restore, deletes all data from the target database before restoring the backup.

Direct Database-to-Database Copies

In addition to backups and restores, you can also transfer data directly between databases with Heroku PGBackups.

To perform a transfer, run the following:

$ heroku pg:copy COBALT GREEN --app example-app

This command copies all data from the COBALT database to the GREEN database in the example-app app.

You can also transfer directly from a database on another app, for example, to copy production data into a staging app for testing purposes.

$ heroku pg:copy example-app::HEROKU_POSTGRESQL_ORANGE_URL GREEN --app example-staging-app

This command copies data from the HEROKU_POSTGRESQL_ORANGE database of the example-app to the GREEN database in example-staging-app.

These commands use a shorthand to identify the databases. For example, COBALT refers to the database called HEROKU_POSTGRESQL_COBALT in the output of heroku addons --app example-app. The first database you create is attached as DATABASE by default. Additional databases are given a color name, such as HEROKU_POSTGRESQL_COBALT. You can useDATABASE,COBALT`, and so on, to select a database in the Heroku Postgres CLI commands.

Visibility

Heroku Postgres must connect to your database using your credentials to capture a backup. This connection counts against your plan connection limit. You can identify connections made by Heroku PGBackups by running the following command from your terminal:

$ heroku pg:psql -c "select * from pg_stat_activity where application_name = 'Heroku Postgres Backups'"

Data Residency

All snapshots captured via pg:backups are stored in the U.S., regardless of where your database is located. To capture logical backups in another region, see Heroku Postgres Logical Backups.

Postgres Continuous Protection for disaster recovery stores the base backup and write-ahead logs (WAL) in the same region that the database is located.

See the Salesforce Infrastructure & Sub-processors document for the list of sub-processors Heroku uses and the list of countries where Heroku data is stored and processed.

Feedback

Log in to submit feedback.

Information & Support

  • Getting Started
  • Documentation
  • Changelog
  • Compliance Center
  • Training & Education
  • Blog
  • Support Channels
  • Status

Language Reference

  • Node.js
  • Ruby
  • Java
  • PHP
  • Python
  • Go
  • Scala
  • Clojure
  • .NET

Other Resources

  • Careers
  • Elements
  • Products
  • Pricing
  • RSS
    • Dev Center Articles
    • Dev Center Changelog
    • Heroku Blog
    • Heroku News Blog
    • Heroku Engineering Blog
  • Twitter
    • Dev Center Articles
    • Dev Center Changelog
    • Heroku
    • Heroku Status
  • Github
  • LinkedIn
  • © 2026 Salesforce, Inc. All rights reserved. Various trademarks held by their respective owners. Salesforce Tower, 415 Mission Street, 3rd Floor, San Francisco, CA 94105, United States
  • heroku.com
  • Legal
  • Terms of Service
  • Privacy Information
  • Responsible Disclosure
  • Trust
  • Contact
  • Cookie Preferences
  • Your Privacy Choices