SafeGrd / Render backup

How to back up a Render Postgres database, and keep a copy past the recovery window

Render backs up paid Postgres databases continuously and can recover one to a point in the last 3 or 7 days, depending on the workspace. A Free database has no recovery at all, and no plan keeps a copy you hold for longer than a week. This page is the dump that does: the external URL, the role, the command, where the file goes, the restore and the check. The last section is how SafeGrd runs it with no server of your own.

What Render's recovery covers

From Render's Postgres backups page, read on 2026-10-08:

WorkspacePoint-in-time recoveryLogical backups
Free databaseNone. "Render does not provide recovery capabilities for databases on the Free compute plan."None; run pg_dump yourself
HobbyThe past 3 daysA .dir.tar.gz you can download, kept 7 days
Pro and aboveThe past 7 daysThe same, kept 7 days

1. The external URL, and the allow list

A Render database has an internal URL, for services in the same region, and an external one for everything else. A backup from outside Render uses the external one:

postgresql://USER:PASSWORD@dpg-example-a.frankfurt-postgres.render.com/DBNAME?sslmode=require

Make a role for the backup that can read and cannot write:

CREATE ROLE backup LOGIN PASSWORD 'a long random password';
GRANT pg_read_all_data TO backup;

2. Dump it

pg_dump --format=custom --no-owner --file=render.dump "$EXTERNAL_DATABASE_URL"

The client has to be at least the server's major version, which Render shows on the database's page. --no-owner keeps Render's generated role name out of the dump, so it restores anywhere.

3. Off Render, encrypted, on a schedule

set -o pipefail
pg_dump -Fc --no-owner "$DATABASE_URL" | age -r "$AGE_RECIPIENT" | aws s3 cp - "s3://$BUCKET/render/$(date -u +%F).dump.age"

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

Create an empty database, on a new Render instance or any PostgreSQL of the same or a newer major version, and restore over its external URL. Stop at the first error:

aws s3 cp "s3://$BUCKET/render/2026-10-08.dump.age" - | age -d -i backup-key.txt > render.dump
pg_restore --exit-on-error --no-owner --dbname "$RESTORE_URL" render.dump

Then compare row counts per table with the source, as How to test that a backup restores shows. Render's own downloadable backup is a different artefact, a .dir.tar.gz of a directory-format dump, and pg_restore takes the unpacked directory the same way.

How SafeGrd does it

SafeGrd takes the backup from a scheduled GitHub Actions job over the external URL, or on a machine it starts for each backup from the connection string, encrypts it before upload, and keeps a copy for as long as the retention you set, not Render's 7 days. 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 The GitHub Actions setup

- uses: safegrd/backup-action@v0
  with:
    config: ${{ secrets.SAFEGRD_CONFIG }}
    database-url: ${{ secrets.DATABASE_URL }}   # the external URL

The setup is the Supabase guide's with Render's external string in DATABASE_URL. With no workflow at all, Back up on SafeGrd under Surfaces in the console takes the same string; a machine SafeGrd starts for each backup dumps and encrypts it, then is destroyed, and the string is sealed and given only to that machine (how). Where SafeGrd's machines connect from fixed addresses, the console shows them, for an allow list that is not open.

Questions

Does this replace Render's point-in-time recovery?

No. Recovery takes the database to any minute in its window and makes a new instance in one click; a dump restores to the moment it was taken. Keep recovery for the quick undo, and the dump for anything older than a week or after the workspace is gone.

Can the daemon run on Render?

As a background worker from the ghcr.io/safegrd/cli image with a persistent disk for its key and config, reading the internal URL. A cron job cannot hold the disk. The workflow keeps nothing running on Render at all.

Related