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
    • Platform Principles
    • Buildpacks
  • 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
      • Working with Node.js
      • Node.js Behavior in Heroku
      • 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
      • Heroku AppLink Reference
      • Getting Started with Heroku AppLink
      • Working with Heroku AppLink
    • Heroku Connect (Salesforce sync)
      • Heroku Connect Administration
      • Heroku Connect Reference
      • Heroku Connect Troubleshooting
    • Other Salesforce Integrations
  • Security
  • Private Spaces
  • Migrating Heroku Postgres Databases to Private Spaces

Migrating Heroku Postgres Databases to Private Spaces

English — 日本語に切り替える

Table of Contents [expand]

  • Migrate with Follower Changeovers
  • Steps to Take After the Migration

Last updated January 13, 2026

Heroku Private Spaces are isolated runtime environments with their own dedicated network to which Heroku apps can be deployed using the Heroku developer experience. Heroku Postgres can run within the boundaries of a Private Space.

The migration instructions in this document apply to moving a database from the current Heroku Common Runtime environment into a Private Space.

This migration can only be done via the Heroku CLI.

 

This article makes the assumption that your Heroku Space has already been provisioned and the app is running inside the Private Space.

Migrate with Follower Changeovers

The follower changeover method lets you migrate a production database from the Common Runtime to a Private Space while the original database is still operating. This migration requires follower databases, which aren’t supported for Essential-tier databases

Migrating databases with a follower changeover entails provisioning a follower for a database in the new Private Space. This process allows the follower to catch up to the old database, and then promote it to be the new primary database for the target application.

The advantage of a follower upgrade is that it requires little downtime, usually less than a minute. Before the changeover, it can take several hours to prepare a new follower (during which your application is still active), so plan accordingly.

1. Provision the Follower Database

Create a follower for your database on the Private Space you’re migrating to:

$ heroku addons:create heroku-postgresql:private-4 -a private-spaces-example -- --follow postgresql-simply-2449
Adding heroku-postgresql:private-4 to private-spaces-example... ~$2.083/hour (max $1500/month)
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
Use heroku addons:docs heroku-postgresql to view documentation

Wait for the follower to catch up to the primary database. The follower is considered “caught up” when it’s within 200 commits of the primary database. You can check how many commits the follower is behind with the Behind By row of the follower database in the pg:info command:

$ heroku pg:info --app private-spaces-example

=== HEROKU_POSTGRESQL_PURPLE
Plan:        Private 4
Status:      Available
...
Following:   DATABASE
Behind By:   125 commits
...
Add-on:   postgresql-shaped-12345

2. Enter Maintenance Mode to Prevent Database Writes

It’s important that no new data is written to your current primary database during the plan change process, because it doesn’t transfer to the new database. To prevent database writes, place your app into maintenance mode. If you have scheduler jobs running as well, disable them.

Your application is unavailable starting at this point in the upgrade process.

$ heroku maintenance:on  --app private-spaces-example
Enabling maintenance mode for private-spaces-example... done

Maintenance mode doesn’t automatically scale down any dynos. Scale down web and any non-web dynos to make sure that no connections are writing data to the database.

$ heroku ps:scale worker=0 --app private-spaces-example
Scaling worker processes... done, now running 0

3. Promote the Follower Database

Now that you’re in maintenance mode and no additional data is 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 private-spaces-example

=== HEROKU_POSTGRESQL_PURPLE_URL
Plan:        Private 4
Status:      Available
...
Following:   DATABASE
Behind By:   0 commits
...
Add-on:   postgresql-shaped-12345

When the follower is caught up and no new data is generated, run the pg:unfollow command to convert the follower into a full, writeable database.

$ heroku pg:unfollow HEROKU_POSTGRESQL_PURPLE --app private-spaces-example
 ›   Warning: Destructive action
 ›   postgresql-shaped-12345 will become writeable and no longer follow DATABASE. This cannot be undone.
 ›

To proceed, type private-spaces-example or re-run this command with --confirm private-spaces-example: private-spaces-example
postgresql-shaped-12345 unfollowing... done

After the unfollow is successful, pg:info shows that the database is now a fork of its parent in the Forked From: DATABASE line.

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 that your application uses:

$ heroku pg:promote HEROKU_POSTGRESQL_PURPLE --app private-spaces-example
Ensuring an alternate alias for existing DATABASE_URL... HEROKU_POSTGRESQL_GREEN_URL
Promoting HEROKU_POSTGRESQL_PURPLE_URL to DATABASE_URL on ⬢ private-spaces-example... done... done

The follower database is now the primary database (though the application isn’t yet receiving new requests).

If you attached your original primary database 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:

$ heroku addons:create heroku-postgresql:private-4 -a private-spaces-example -- --follow DATABASE_URL

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 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 private-spaces-example

4. Exit Maintenance Mode

To resume normal application operation, scale any non-web dynos back to their original levels. (If the application wasn’t previously using non-web dynos, skip this step in order to avoid scaling any dynos that you don’t need).

$ heroku ps:scale worker=1

Finally, turn off maintenance mode.

$ heroku maintenance:off --app private-spaces-example
Disabling maintenance mode for private-spaces-example... done

Your application is now receiving requests to your migrated database instance. You can confirm your app is receiving requests by running heroku pg:info. The database denoted by DATABASE_URL is considered the primary database for your Private Space application.

If your Heroku Postgres database isn’t connected to a Heroku app, you must retrieve the connection string of the new primary, migrated database. Then, update your application and any external systems to point them to the new database.

Steps to Take After the Migration

The follower failover migration method involves creating a new database add-on in your Private Space, and your old database add-on in the Common Runtime isn’t automatically deprovisioned.

After migrating your database, be sure to deprovision your old primary database:

$ heroku addons:destroy HEROKU_POSTGRESQL_GREEN_URL --app common-runtime-example

You must reassign the dataclips that were associated with the old primary database to the new database. Follow the instructions on Dataclip recovery to resolve any recoverable Dataclips.

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