Managing Heroku Postgres using the CLI
Last updated December 27, 2021
Table of Contents
Heroku Postgres is integrated directly into the Heroku CLI and offers many helpful commands that simplify common database tasks.
To see all PostgreSQL databases provisioned by your application and the identifying characteristics of each (such as database size, status, number of tables, and PG version), use the
heroku pg:info command:
$ heroku pg:info === HEROKU_POSTGRESQL_RED Plan Standard 0 Status available Data Size 82.8 GB Tables 13 PG Version 12.5 Created 2012-02-15 09:58 PDT === HEROKU_POSTGRESQL_GRAY Plan Standard 2 Status available Data Size 82.8 GB …
To continuously monitor the status of your database, pass
pg:info through the unix watch command:
$ watch heroku pg:info
psql is the native PostgreSQL interactive terminal and is used to execute queries and issue commands to the connected database.
To establish a
psql session with your remote database, use
You must have PostgreSQL installed on your system to use
$ heroku pg:psql Connecting to HEROKU_POSTGRESQL_RED... done psql (12.5, server 12.5) SSL connection (cipher: DHE-RSA-AES256-SHA, bits: 256) Type "help" for help. rd2lk8ev3jt5j50=> SELECT * FROM users;
The database located at
DATABASE_URL is used by default. If you have more than one database, specify the database you want to connect to as the first argument to the command. You can use just the color as a shorthand:
$ heroku pg:psql gray Connecting to HEROKU_POSTGRESQL_GRAY... done ...
pg:push and pg:pull
For a more in-depth guide on working with backups, read the import and export guide.
pg:pull can be used to pull remote data from a Heroku Postgres database to a database on your local machine. The command looks like this:
$ heroku pg:pull HEROKU_POSTGRESQL_MAGENTA mylocaldb --app sushi
This command creates a new local database named
mylocaldb and then pulls data from the database at
DATABASE_URL from the app
sushi. To prevent accidental data overwrites and loss, the local database must not exist. You’ll be prompted to drop an existing local database before proceeding.
If providing a Postgres user or password for your local DB is necessary, use the appropriate environment variables like so:
$ PGUSER=postgres PGPASSWORD=password heroku pg:pull HEROKU_POSTGRESQL_MAGENTA mylocaldb --app sushi
As with all
pg:* commands, you can use shorthand database identifiers here. For example, to pull data from
HEROKU_POSTGRESQL_RED on the app
sushi, you could run
heroku pg:pull sushi::RED mylocaldb.
pg:push pushes data from a local database into a remote Heroku Postgres database. The command looks like this:
$ heroku pg:push mylocaldb HEROKU_POSTGRESQL_MAGENTA --app sushi
This command takes the local database
mylocaldb and pushes it to the database at
DATABASE_URL on the app
sushi. To prevent accidental data overwrites and loss, the remote database must be empty. You’ll be prompted to
pg:reset a remote database that isn’t empty.
Usage of the
PGPASSWORD for your local database is also supported for
pg:push, just like for the
These commands rely on the
pg_restore binaries that are included in a Postgres installation. It’s common, however, for the wrong binaries to be loaded in
$PATH. Errors such as
! createdb: could not connect to database postgres: could not connect to server: No such file or directory ! Is the server running locally and accepting ! connections on Unix domain socket "/var/pgsql_socket/.s.PGSQL.5432"? ! ! Unable to create new local database. Ensure your local Postgres is working and try again.
pg_dump: server version: 12.5; pg_dump version: 10.14 pg_dump: aborting because of server version mismatch pg_dump: *** aborted because of error pg_restore: [archiver] input file is too short (read 0, expected 5)
are both often a result of this incorrect
$PATH problem. This problem is especially common with Postgres.app users, as the post-install step of adding
$PATH is easy to forget.
pg:ps, pg:kill, pg:killall
These commands give you view and control over currently running queries.
pg:ps command queries the
pg_stat_activity view in Postgres to give a concise view into currently running queries.
$ heroku pg:ps procpid | source | running_for | waiting | query ---------+---------------------------+-----------------+---------+----------------------- 31776 | psql | 00:19:08.017088 | f | <IDLE> in transaction 31912 | psql | 00:18:56.12178 | t | select * from hello; 32670 | Heroku Postgres Data Clip | 00:00:25.625609 | f | BEGIN READ ONLY; select 'hi' (3 rows)
The procpid column can then be used to cancel or terminate those queries with
pg:kill. Without any arguments, pg_cancel_backend is called on the query and it attempts to cancel the query. If it fails, use the
--force option to issue pg_terminate_backend to drop the entire connection for that query.
$ heroku pg:kill 31912 pg_cancel_backend ------------------- t (1 row) $ heroku pg:kill --force 32670 pg_terminate_backend ---------------------- t (1 row)
pg:killall is similar to
pg:kill except it cancels or terminates every query on your database.
Promote a database to be the primary for your app with the
heroku pg:promote command.
pg:promote updates the value of the
DATABASE_URL config var with the newly promoted database’s connection string. It also creates an alternate attachment for the old primary database, assigned with a new
HEROKU_POSTGRESQL_<color>_URL config var. The promotion process triggers a release and restarts the app.
$ heroku pg:promote HEROKU_POSTGRESQL_GRAY_URL -a example-app Ensuring an alternate alias for existing DATABASE_URL... HEROKU_POSTGRESQL_PINK_URL Promoting HEROKU_POSTGRESQL_GRAY_URL to DATABASE_URL... done
pg:promote for a follower database doesn’t automatically make it unfollow its leader. Run
pg:unfollow on followers to stop replication before promoting it.
After a promotion, the demoted database still exists and incurs charges. Delete your old primary database with
heroku addons:destroy HEROKU_POSTGRESQL_COLOR.
Promotions When Using Connection Pooling
If your old primary used Connection Pooling attached with the default name
pg:promote reattaches the connection pooler to the new primary.
If you use Connection Pooling attachments under non-default names, you must update them after running
pg:promote. Activate Connection Pooling on your new primary to repoint the connection pooling URL:
$ heroku pg:connection-pooling:attach DATABASE_URL --as MY_DATABASE_CONNECTION_POOL -a example-app
Heroku Postgres provides convenient access to the credentials and location of your database. This makes it easier to use a GUI to access your instance.
The database name argument must be provided with
pg:credentials:url command. Use
DATABASE for your primary database.
$ heroku pg:credentials:url DATABASE Connection info string: "dbname=dee932clc3mg8h host=ec2-123-73-145-214.compute-1.amazonaws.com port=6212 user=user3121 password=98kd8a9 sslmode=require"
It’s a good security practice to rotate the credentials for important services on a regular basis. On Heroku Postgres, you can use
heroku pg:credentials:rotate to rotate credentials.
$ heroku pg:credentials:rotate HEROKU_POSTGRESQL_GRAY_URL
When you issue this command, new credentials are created for your database and the related config vars on your Heroku application are updated. However, on Standard, Premium, and Enterprise tier databases, old credentials aren’t removed immediately. All of the open connections remain open until the currently running tasks complete, then those credentials are updated. This ensures background jobs or other workers running on your production environment aren’t abruptly terminated, potentially leaving the system in an inconsistent state.
The PostgreSQL user your database is assigned doesn’t have permission to create or drop databases. To drop and recreate your database use
$ heroku pg:reset DATABASE