Changing the Plan or Infrastructure of a Heroku Postgres Database
Last updated July 26, 2024
Table of Contents
This article describes available methods for changing the plan or underlying infrastructure of a Heroku Postgres database.
This article documents the process of upgrading your PostgreSQL plan and infrastructure, which in some cases can also change your PostgreSQL version. If you only want to upgrade your PostgreSQL version, see Upgrading the Version on Heroku Postgres Databases.
Heroku supports three methods for changing Postgres plans and infrastructure. All methods require some application downtime to ensure that no data is lost during the update.
Upgrade Method | Description |
---|---|
heroku addons:upgrade | Description: Updates the plan and infrastructure of a production database while preserving its major PostgreSQL version. Compatible plans: Works for all Heroku Postgres plans. You can use this command to change Essential-tier databases to another plan in that tier. To upgrade Essential-tier databases to plans on other tiers, use pg:copy instead. Downtime required: Requires up to several hours to prepare a replacement (during which the application can remain active), and less than 1 minute of downtime during the changeover. Follower databases: Repoints any database followers to the new primary. |
Follower changeover | Description: Updates the plan and infrastructure of a production database while preserving its major PostgreSQL version. Compatible plans: Only works with Standard, Premium, Private, or Shield tier databases. Version upgrades: Can be used to upgrade the PostgreSQL minor version to the latest available. Downtime required: Requires up to several hours to prepare a follower (during which the application can remain active), and less than 1 minute of downtime during the changeover. Follower databases: Requires recreation of followers to point to the new primary. In general, addons:upgrade is preferable to a follower changeover, due to follower repointing and Heroku-controlled mechanisms for running maintenance. |
pg:copy | Description: Works for all update scenarios. Required for all version changes that involve a deprecated mini or basic database, or to upgrade an Essential-tier database plan to a plan in another tier. Version upgrades: Can be used to upgrade major PostgreSQL version. Downtime required: Requires downtime of about 3 minutes per GB, though this amount can vary substantially. Follower databases: Requires recreation of followers to point to the new primary. |
Updating with addons:upgrade
Essential-Tier
To change an Essential-tier database plan to another plan in the same tier, running addons:upgrade
starts the upgrade immediately without waiting for or running a scheduled maintenance.
$ heroku addons:upgrade HEROKU_POSTGRESQL_CRIMSON_URL heroku-postgresql:essential-0 -a example-app
Changing HEROKU_POSTGRESQL_CRIMSON_URL on example-app from heroku-postgresql:mini to heroku-postgresql:essential-0... done, ~$0.007/hour (max $5/month)
Your database's plan is being changed from mini to essential-0.
Running addons:upgrade
to upgrade to an essential-*
plan puts the database in read-only mode, so no writes happen during the upgrade. You can also put your app in maintenance mode before starting the upgrade so no new data is written to your database during the upgrade process. The upgrade transfers data to a new database on the chosen Essential plan and updates the config vars to point to the new Essential database.
Standard-Tier and Higher
You can’t use addons:upgrade
to change a Standard-tier or higher database to an Essential-tier database. Instead, you can use pg:copy
.
To update a database with addons:upgrade
, you:
- Run
heroku addons:upgrade
on your database - Run or wait for your scheduled maintenance window
Updating with addons:upgrade
requires little app downtime (less than a minute). Before the changeover, however, it can take several hours to prepare the replacement (during which your application is still active), so plan accordingly.
1. Run the heroku addons:upgrade
Command
This command prepares your database for a plan upgrade. This process isn’t instant, and can take several hours for larger databases.
$ heroku addons:upgrade HEROKU_POSTGRESQL_LAVENDER_URL heroku-postgresql:premium-4 -a example-app
Changing HEROKU_POSTGRESQL_LAVENDER_URL on tc-data-test from heroku-postgresql:standard-0 to heroku-postgresql:premium-4... done, ~$1.042/hour (max $750/month)
Your database's plan is being changed.
This triggers a maintenance that you can run with `heroku data:maintenances:run`.
When your database is ready for an upgrade, you receive an email about upcoming scheduled maintenance for your database
2. Run (or Wait for) the Scheduled Maintenance
When ready, the addons:upgrade
command schedules your database for a maintenance that performs the upgrade on the database.
This process is the same as the maintenance mechanism described in Heroku Postgres Maintenance Windows.
When you’re ready to run maintenance on your database, refer to Running a maintenance manually. After the maintenance is complete, your database will be on hardware matching the new plan.
If your database has one or more followers, when the upgrade maintenance occurs, Heroku attempts to point the followers to the replacement database. Pointing the followers to the replacement requires the follower database to be restarted. In some cases, if we’re unable to point the follower at the replacement, we automatically prepare and promote a replacement database.
If you want to stop an upgrade, see this Help article.
Updating with Follower Changeover
Changing a plan with a follower changeover involves these manual steps:
- Provision a follower database with the plan you want to change to, and wait for it to catch up to your primary database. If you change to update the underlying hardware for your plan, choose the same plan your database is currently on.
- Place your app in maintenance mode.
- Unfollow and promote the follower to be your primary database.
- Exit maintenance mode.
For a more automated method, use addons:upgrade
.
Before the changeover, it can take several hours to complete the manual sets of preparing the follower and placing your app in maintenance mode, so plan accordingly. After preparing the steps, the follower changeover requires usually less than a minute app downtime to complete.
1. Provision the Follower Database
Create a follower for your database and wait for the follower to catch up to the primary database:
The addons:create
example follows the syntax for Heroku CLI v9.0.0 or later. If you’re on v8.11.5 or earlier, use the command:
$ heroku addons:create heroku-postgresql:standard-2 --follow HEROKU_POSTGRESQL_LAVENDER_URL --app example-app
$ heroku addons:create heroku-postgresql:standard-2 --app example-app -- --follow HEROKU_POSTGRESQL_LAVENDER_URL
Creating heroku-postgresql:standard-2 on example-app... $200/month
! WARNING: Follower will become available for read-only queries when up-to-date.
Use `heroku pg:wait` to track status.
postgresql-shaped-12345 is being created in the background. The app will restart when complete...
Use heroku addons:info postgresql-shaped-12345 to check creation progress
$ heroku addons:wait
Creating postgresql-shaped-12345... done
Created postgresql-shaped-12345 as HEROKU_POSTGRESQL_WHITE_URL
The follower is considered “caught up” when it is within 200 commits of the primary database. You can check how many commits the follower is behind with the pg:info
command (see the Behind By
row of the follower database):
$ heroku pg:info --app example-app
=== HEROKU_POSTGRESQL_LAVENDER
Plan: Standard 0
Status: Available
...
=== HEROKU_POSTGRESQL_WHITE
Plan: Standard 2
Status: Available
...
Following: HEROKU_POSTGRESQL_LAVENDER (DATABASE_URL)
Behind By: 125 commits
2. Enter Maintenance Mode to Prevent Database Writes
It’s important that no new data is written to your current primary database during the upgrade process, because it doesn’t transfer to the new database. To accomplish this, place your app into maintenance mode. If you have scheduler jobs running as well, disable them.
Maintenance mode doesn’t automatically scale down dynos. Scale down web and any non-web dynos (for example, heroku ps:scale worker=0
) to ensure that no connections are writing data to the database.
If the database you’re updating is used by Heroku Connect, pause the synchronization at this point to ensure that the connection isn’t writing data to the database. Instructions are available in Heroku Connect: Upgrading your database.
Your application is unavailable starting at this point in the upgrade process.
$ heroku maintenance:on
Enabling maintenance mode for example-app... done
3. Promote the Follower Database
Now that you are in maintenance mode and no additional data is being written to the primary database, you can promote the follower database to take over from the current primary one.
Wait for the follower database to fully catch up to the primary (as indicated by being behind by 0 commits
).
$ heroku pg:info --app example-app
=== HEROKU_POSTGRESQL_LAVENDER_URL
Plan: Standard 0
Status: available
...
=== HEROKU_POSTGRESQL_WHITE_URL
Plan: Standard 2
Status: available
...
Following: HEROKU_POSTGRESQL_LAVENDER_URL (DATABASE_URL)
Behind By: 0 commits
When the follower is caught up and no new data is being generated, issue an unfollow
command to convert the follower into a full, writeable database.
$ heroku pg:unfollow HEROKU_POSTGRESQL_WHITE_URL --app example-app
▸ WARNING: Destructive action
▸ postgresql-shaped-12345 will become writeable and no longer follow HEROKU_POSTGRESQL_LAVENDER. This cannot be undone.
▸
▸ To proceed, type example-app or re-run this command with --confirm example-app
> example-app
postgresql-shaped-12345 unfollowing... done
After the unfollow is successful, pg:info
shows that the database is now a fork of its parent (Forked From: HEROKU_POSTGRESQL_LAVENDER
).
You can also verify that the database is out of read-only mode by running the SQL command: SELECT pg_is_in_recovery();
, which returns false
when the new database is ready for read-write connections.
Then, promote it to set it as the primary database (at the DATABASE_URL
location) used by your application:
$ heroku pg:promote HEROKU_POSTGRESQL_WHITE_URL --app example-app
Promoting HEROKU_POSTGRESQL_WHITE_URL to DATABASE_URL on example-app... done
The follower database is now the primary database (although the application isn’t yet receiving new requests).
If your original primary database was attached to multiple apps, you must attach your new database to those apps with heroku addons:attach
.
After the changeover, other followers of your original primary database don’t automatically start to follow your new primary. You must recreate followers to point to your new primary database.
Create followers for the new primary database as needed. If you’re using Heroku CLI v9.0.0 or later, run the command:
$ heroku addons:create heroku-postgresql:standard-0 -a example-app -- --follow DATABASE_URL
If you’re using Heroku CLI v8.11.5 and earlier, run the command:
$ heroku addons:create heroku-postgresql:standard-0 --follow DATABASE_URL -a example-app
Be sure to deprovision your old followers after you no longer need them.
If your old primary was using connection pooling, and it was attached with the default name DATABASE_CONNECTION_POOL
, the promote reattaches the connection pooler to the new primary under the same name DATABASE_CONNECTION_POOL
.
Attachments under non-default names aren’t reattached. You must activate connection pooling on your new primary if you wish to keep using connection pooling on your new primary with the same non-default name as the old primary:
$ heroku pg:connection-pooling:attach DATABASE_URL --as MY_DATABASE_CONNECTION_POOL -a example-app
4. Exit Maintenance Mode
To resume normal application operation, scale any non-web dynos back to their original levels. For example, if you had previously scaled down a worker
dyno, you would scale it back up now with heroku ps:scale worker=1
.
Finally, turn off maintenance mode:
$ heroku maintenance:off
Disabling maintenance mode for example-app... done
Your application is now receiving requests to your updated database instance. You can confirm maintenance mode is off by running heroku pg:info
. The database denoted by DATABASE_URL
is considered the primary database.
If your Heroku Postgres database isn’t connected to a Heroku application, you must retrieve the HEROKU_POSTGRESQL_WHITE_URL
and update your application to use it as your primary database.
Updating with pg:copy
The pg:copy
command supports updates between all supported Heroku Postgres plans and versions. Additionally, it’s the only supported method for version changes that involve a deprecated mini
or basic
Essential-tier database, or to upgrade an Essential-tier database to a plan in another tier.
Instructions for using pg:copy
are available in Upgrading Heroku Postgres Databases.
Deprovisioning the Old Primary Database
After you update your database with either a follower changeover or pg:copy
, be sure to deprovision your old primary database:
$ heroku addons:destroy HEROKU_POSTGRESQL_LAVENDER_URL
Dataclips that were associated with the old primary database must be reassigned to the new database. Follow the instructions on Dataclip recovery to resolve any recoverable Dataclips.