There are many ways to move a PostgreSQL database between servers, but for a production-grade setup,where roles already exist and you simply want to migrate one database cleanly, the safest path is to create the target database first and restore into it.

This approach keeps ownerships and permissions consistent, avoids overwriting roles, and works perfectly between PostgreSQL servers of the same major version (in this case, version 15).

Preparing the Destination

Start by making sure the role (user) already exists on the destination. In this example, we’ll migrate a database named myapp that belongs to the role myapp_user.

Check if the role exists.

If not found, create it.

We won’t import global roles from the source, because I already manage users manually.

Step 1, Create a Backup on the Source Server

On the source host, run:

This command creates a custom-format dump file that can be restored flexibly and in parallel.

Check the file.

Step 2, Copy the Dump to the Destination

Send the dump file securely to the new server.

Or, if you prefer to pull it.


Step 3, Create the Target Database

Now on the destination server:

This prepares an empty database owned by the correct role.
Confirm.

Step 4, Restore the Dump

Restore the data into the new database.

If you only want to import schema and data (ignoring ownership or ACL info from the dump), use.

Large databases can be restored in parallel.

Step 5, Verify the Result

List tables.

Log in as the application user.

Inside psql.

If that works, the migration is complete.

Optional, Direct Pipe Transfer (No Dump File)

If the servers are connected by SSH and you prefer streaming,

This performs the same transfer in one step without creating a dump file on disk.

Summary

StepActionCommand
1Dump database on sourcepg_dump -Fc -f /tmp/myapp.dump myapp
2Copy to destinationscp /tmp/myapp.dump user@pg-dst:/tmp/
3Create DB on destinationcreatedb -O myapp_user myapp
4Restorepg_restore -d myapp /tmp/myapp.dump
5Verifypsql -d myapp -c "\dt"

Closing Notes

When both PostgreSQL instances are on version 15, this method is safe, idempotent, and easy to automate.

Creating the database first and assigning it to the same role keeps your access structure intact, ideal for teams managing multiple environments with predefined roles.

It’s the same principle you’d apply in any infrastructure move, build the container first, then pour the data in.

Leave A Comment

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.