Restore a Supabase backup

If you’re here on a bad day: your backups live in your own bucket, in plain formats, so every path on this page works with or without BackupDrill in the loop. Each snapshot sits at <prefix>/<project>/<timestamp>/ and contains dump.pgcustom, a storage/ tree with your files, and a checksummed manifest.json.

First, the Supabase gotcha

Restoring the database alone does not bring back your Storage files. A database restore only recovers storage.objects — the metadata — while the actual files live in a separate object store. That is exactly why BackupDrill snapshots include the files themselves under storage/: a full recovery is the database restore plus putting those files back.

Path A — you hold the artifacts

Because backups are written to your bucket, recovery never depends on our service being up, or on you still being a customer. Find the snapshot you want by timestamp in your bucket, then use the CLI (path B) or plain pg_restore(path C) against it. If you’re a hosted customer and want a human on the line, email support@backupdrill.com.

Path B — the CLI restore command

With the CLI configured for your bucket, restore puts the database back into a target you name and pulls the Storage files down to a local folder:

backupdrill restore \
  --target-database-url "postgresql://…/postgres" \
  --storage-dir ./recovered

Path C — raw pg_restore

No CLI, no dependencies beyond Postgres client tools: download dump.pgcustom from the snapshot folder and restore it by hand.

pg_restore --clean --if-exists --no-owner \
  --dbname "<target-connection-string>" dump.pgcustom

Remember the gotcha above: this restores the database only. Your Storage files are sitting next to the dump under storage/.

Why this page should be boring

Restore drills exist precisely so this page holds no surprises. On the hosted service, every drill restores your latest snapshot into a throwaway Postgres and verifies the archive sha256, that pg_restorecompletes with post-data objects applied, and that table counts match with no missing or unexpectedly empty tables — with an email the moment one fails. If you haven’t set that up yet, the quickstart takes six steps.