Guide
Backing up Railway Postgres
Railway's Postgres runs on a volume attached to your service. Volume-level snapshots and platform features help, but the copy that saves you is the one that leaves the platform — under your control, restorable anywhere.
Dump it
Grab the public connection string from your Postgres service's Connect tab (the ...proxy.rlwy.net:<port> one — the internal hostname only resolves inside your Railway project):
pg_dump -Fc -f "railway-$(date +%F).dump" \
"postgresql://postgres:<PWD>@<region>.proxy.rlwy.net:<PORT>/railway"
Schedule it
- Inside Railway: a tiny cron service in the same project can use the internal hostname and push dumps to S3/R2/B2 — no egress through the proxy.
- Outside Railway: a GitHub Actions cron with the public string is the zero-infra option and doubles as an availability check.
- Either way: custom format (
-Fc), encrypt before upload, keep at least 14 daily copies, and store them in a bucket you own on a different provider than the database.
The part that makes it a backup
Every failed restore we've seen had months of "successful" dumps behind it. Restore into a throwaway container, compare table counts, validate constraints, run one query that should never return zero:
docker run -d --name drill -e POSTGRES_PASSWORD=drill -p 5499:5432 postgres:16
pg_restore --no-owner -h localhost -p 5499 -U postgres -d postgres railway-latest.dump
psql -h localhost -p 5499 -U postgres -c "SELECT count(*) FROM users;"
docker rm -f drill
Full checklist: the 5-step drill.
Offsite, encrypted, restore-tested
pgProof connects to Railway with the public string, dumps on schedule, and restore-tests every backup in a version-matched container. You get proof weekly and an alert the moment a drill fails.
Join the early-access waitlist