How to back up a Postgres database on Fly.io, and keep a file you hold
Fly.io has two kinds of Postgres. Managed Postgres (MPG) is the current one, a cluster inside your organization's private network with automatic backups, a connection pooler and an API. Fly Postgres, the older app you ran yourself, is deprecated in favour of it. Neither gives you a file outside Fly. This page is that file: how to reach the database from inside the network and from your laptop, the command, where the copy goes, the restore and the check. The last section is how SafeGrd runs it as a Machine beside the database.
What Fly's backups cover
From Fly's documentation, read on 2026-10-08:
- Managed Postgres lists "Automatic backups and recovery" on every plan,
with
fly mpg backup createandfly mpg backup listin the CLI and a Machines API call that restores a backup or a point in time to a new cluster. The docs state no retention period and no way to download a backup. Storage is billed per GB used. - Fly Postgres (unmanaged) "is no longer maintained, and Fly.io Support is not able to provide support or guidance for it" (its "What you should know" page). It takes daily volume snapshots. Fly points to Managed Postgres as the replacement.
- Both live in the organization. A cluster deleted with the org, by a script with the API token, or by a person, takes its backups with it.
1. Reach the database
An MPG cluster has two hostnames on the private network. Fly's client page says SSL is enabled by default on every MPG connection, so no flag is needed:
- Use the direct hostname. PgBouncer in transaction mode does not keep a
session, and
pg_dumpneeds one to read every table from one snapshot. - From inside Fly: any Machine in the same organization resolves
*.flympg.net. That is where a scheduled backup belongs. - From your laptop:
fly mpg proxyopens a local port that forwards into the network; Fly's example islocalhost:16380, and you replaceflympg.netwithlocalhostin the direct string. Fly's import guide notes the cluster "runs within your Fly Private Network," so a restore or dump from outside goes through the proxy or your organization's WireGuard.fly mpg connectdoes the same and openspsql. - Fly Postgres (unmanaged) is reached the same way from inside, at
APP.internal:5432. Exposing it to the internet takes a public IP and apg_tlsservice infly.toml; the archived page has the steps.
Make a role for the backup that can read and cannot write, so a leaked credential changes nothing:
2. Dump it
The client has to be at least the server's major version; SELECT version()
says which. --no-owner keeps fly-user out of the dump, so it
restores anywhere.
3. Off Fly, encrypted, on a schedule
The natural place to run it is a small Machine in the same organization, on a schedule, with
the direct string in a secret. Tigris, the object storage Fly offers, is S3-compatible and
in the same network; a bucket at another provider is the copy that does not share Fly's
account.
set -o pipefail makes a failed dump fail the job instead of uploading a
truncated file. The bucket policy, a key that cannot delete and the lock on the bucket are
in the S3 guide and
the Object Lock guide.
4. Restore, and check it
Into a new MPG cluster: through fly mpg proxy, as Fly's import guide does.
Into anything else: an empty database on any PostgreSQL of the same or a newer major
version. Stop at the first error:
Then compare row counts per table with the source, as How to test that a backup restores shows. Fly's own restore makes a new cluster from Fly's backup and is the right tool for a quick undo; it does not test the file you hold.
How SafeGrd does it
SafeGrd runs as a Machine in your organization, from the ghcr.io/safegrd/cli
image, with a volume for its key and config. It resolves the cluster's direct hostname on
the private network, so the read costs no egress, and a sandbox drill runs on the
PostgreSQL server the image carries. SafeGrd does the same job on every platform; the PostgreSQL page has what it dumps, how it encrypts, and what a drill checks.
Run your first Fire Drill Read the install guide
fly launch --image ghcr.io/safegrd/cli --no-deployin an empty directory makes the app; add a volume (fly volumes create safegrd) mounted at/home/safegrd/.safegrdinfly.toml, and the direct connection string as a secret.- Deploy, then
fly ssh consoleand runsafegrd enrollonce, which signs the host in and registers it. Add the database as a surface in the SafeGrd console, with the read-only role. - The image's default command is
safegrd daemon run, which backs up and drills on the surface's schedule. Set the Machine to stay running; the daemon's own clock decides when a backup is due.
A database with a public hostname, an unmanaged Fly Postgres you exposed, works from a GitHub Actions workflow too. An MPG cluster has no public hostname, so the Machine is the host.
Questions
Does this replace Fly's backups?
No. Fly's own restore is the quick way to a new cluster from a recent state. The dump outside Fly is the copy you can keep as long as you like, restore anywhere, and hand to someone.
What does the Machine cost?
Fly bills a Machine per second it runs. The backup reads over the private network, so there is no egress for the read; a sandbox drill needs memory for the database it loads, so size the Machine for the largest surface it drills.
Related
- How to back up a PostgreSQL database: pg_dump's formats and flags, restore and the check
- Railway backup: the same job on Railway's private network
- The daemon: schedules, check-ins and what it does when the server is unreachable