How to copy a PostgreSQL database to another server

Refresh staging from production, move to a new host, or pull a local copy, with pg_dump and pg_restore in two commands.

Updated October 14, 2026 · 3 min read

Short on time? PostgresBackup does everything on this page from a Windows app: scheduled pg_dump backups, retention and one-click restores. Download it free.

Copying a database from one PostgreSQL server to another is a backup and a restore back to back. You'll need it to refresh a staging database from production, to move from one host to another (say Heroku to Neon), or to pull a production copy onto your laptop for debugging.

The two-command version

Dump from the source in custom format, then restore into the target:

PowerShell
$bin = 'C:\Program Files\PostgreSQL\18\bin'

# 1. Dump the source
& "$bin\pg_dump.exe" -h prod.example.com -U app -F c -f "$env:TEMP\shop.dump" shop

# 2. Create the target database and restore into it
& "$bin\createdb.exe" -h localhost -U postgres shop_copy
& "$bin\pg_restore.exe" -h localhost -U postgres -d shop_copy --no-owner --no-privileges "$env:TEMP\shop.dump"
  • --no-owner makes the restoring user own everything instead of trying to recreate the source's roles, which usually don't exist on the target.
  • --no-privileges skips GRANTs for those same missing roles. Leave both off only when the target has the same roles as the source.
  • Use client tools at least as new as the source server (why). The target can be newer than the source, which makes this a clean way to upgrade major versions.

Add $env:PGSSLMODE = 'require' before a command that talks to a hosted database.

Copying over an existing database

To refresh a target that already has the tables (staging, typically), either drop and recreate it:

PowerShell
& "$bin\dropdb.exe" -h staging.example.com -U postgres --if-exists shop_staging
& "$bin\createdb.exe" -h staging.example.com -U postgres shop_staging

or let pg_restore remove what it's about to recreate:

PowerShell
& "$bin\pg_restore.exe" -h staging.example.com -U postgres -d shop_staging --clean --if-exists --no-owner --no-privileges "$env:TEMP\shop.dump"

--clean --if-exists drops each object in the dump before recreating it. Objects that exist only on the target (a table you created on staging) stay. To end up with an exact copy, drop and recreate the database.

Big databases: parallel dump and restore

With the directory format, both sides can use several connections:

PowerShell
& "$bin\pg_dump.exe" -h prod.example.com -U app -F d -j 4 -f "$env:TEMP\shop_dir" shop
& "$bin\pg_restore.exe" -h localhost -U postgres -d shop_copy -j 4 --no-owner --no-privileges "$env:TEMP\shop_dir"

-j 4 uses four parallel jobs. Don't go beyond the CPU cores of the server being read.

Piping without a file

On Linux people often pipe pg_dump | psql. On Windows PowerShell 5.1, pipes between native programs pass text and re-encode it, which corrupts custom-format output. Stick to the file, as above. It's also a backup if the restore fails halfway.

Copying only some tables

PowerShell
& "$bin\pg_dump.exe" -h prod.example.com -U app -F c -t public.customers -t public.orders -f "$env:TEMP\two-tables.dump" shop

Or dump everything and restore selectively with pg_restore -t orders. Excluding large log tables from a staging refresh is common: --exclude-table-data=public.audit_log keeps the table but not its rows.

Things that don't come along

  • Roles and their passwords: create them on the target first, or use --no-owner --no-privileges.
  • Extensions must be available on the target server. Hosted providers support different lists.
  • Sequences come along with their current values, so new rows don't collide.

How PostgresBackup does it

PostgresBackup's Clone does exactly this from a dialog. Pick the source server and database, pick the target (it creates the database if it doesn't exist), and click Clone. It runs pg_dump and pg_restore for you, restores with several parallel jobs (one per processor core, up to 4), shows progress table by table, and checks that every table arrived. Before it starts, it checks that the drive holding its temporary dump file has room, and you can put that file on another drive. It asks before overwriting anything, and it refuses to clone a database onto itself. Cloning is free, with or without a license.

The shortcut

Rather not maintain a backup script?

PostgresBackup is a Windows app that does all of this for you, with nothing to script and nothing to remember.

  • Scheduled pg_dump backups from a background service that starts with Windows
  • Keep the last N files plus hourly, daily, weekly, monthly and yearly copies
  • Restore any backup, or clone a database to another server, in a few clicks
  • PostgreSQL client tools included; standard .dump files, no lock-in
  • No account, no subscription, nothing leaves your machine

Clones, restores and manual backups are free. Scheduled backups are free for 14 days, then $9.99 once (launch price; $24 from January 1).