Quickstart: hosted Supabase backups

Six steps from zero to a Supabase project that backs itself up — database, plus Storage files once you add its keys — into a bucket you own, with restore drills on a schedule and an email when a backup or drill fails. Prefer to run it yourself? Use the open-source CLI instead.

01

Create an account

Sign in at app.backupdrill.com/login — the login page handles signup too. No credit card: every new account starts on the Free plan and stays there unless you subscribe.

02

Connect your Supabase project

Click Connect Supabase. You authorize BackupDrill on the organization you pick — two scopes, shown on the consent screen: Database (read + write) and Projects (read) — then choose the project. BackupDrill creates a dedicated read-only backup role in it (named backupdrill_…, with BYPASSRLS so pg_dump can read RLS-protected tables) and tests the connection from the network your backups run from. No database password. The authorization token lives only in a short-lived cookie in your browser (at most 10 minutes), is deleted after the connection is set up successfully (otherwise it expires within 10 minutes), and is never persisted on our servers; only that role’s connection string is stored, sealed-box encrypted. The project page shows the three-line SQL that revokes the role.

Two prerequisites: the project must run Postgres 16 or newer (creating a BYPASSRLSrole on 15 needs a superuser, which hosted projects don’t have), and if you use Supabase Network Restrictions, allow BackupDrill’s backup IP first — the connection test tells you if it’s blocked.

Prefer not to authorize? Choose Run the SQL yourself: paste the Session pooler string exactly as Supabase shows it (leave [YOUR-PASSWORD] as is), run the generated three-line SQL in the Supabase SQL Editor, and click I ran it. Same role, same test — the password is generated in your browser and, like every credential, stored sealed-box encrypted for the backup worker.

Or paste a connection string (the classic path, needs your database password): use the Session pooler string from the Connect button at the top of the Supabase dashboard, not the Direct one — it resolves to IPv6 only.

On that path the postgres user works as-is — it owns your tables, so dumps pass row-level security. A least-privilege backup_reader role is an advanced option with two gotchas: pg_dump needs select on sequencestoo, and it errors on any RLS-enabled table it can’t bypass — so it only works if your schema has no RLS tables:

-- replace <generate-a-strong-password> before running
create role backup_reader with login password '<generate-a-strong-password>';
grant usage on schema public to backup_reader;
grant select on all tables in schema public to backup_reader;
grant select on all sequences in schema public to backup_reader;
alter default privileges in schema public grant select on tables to backup_reader;
alter default privileges in schema public grant select on sequences to backup_reader;

03

Point it at your own bucket

Backups are written to a bucket you own — S3, R2, or B2 — never to our storage. Provide the endpoint, region, bucket name, access key ID, and secret access key. No bucket yet? The bucket setup guide has exact click-paths for all three providers. For Cloudflare R2:

Endpoint: https://<account>.r2.cloudflarestorage.com
Region:   auto

R2 is addressed path-style: the bucket name travels in the request path, so the endpoint stays the same for every bucket in your account. Because the snapshots land in your bucket, they stay yours — cancel any time and every path to recovery still works.

04

Pick your schedule

Cadence follows your plan:

PlanPriceBackupsDrillsNotes
Free$0WeeklyOne-time1 project
Solo$19/monthDailyWeeklyEmail alerts
Team$49/monthDailyWeeklyFor small teams
Agency$99/monthDailyWeeklyClient PDF reports

05

Your first backup runs within a few minutes

Nothing else to configure — the first backup kicks off within a few minutes of connecting, and later runs follow your plan’s schedule. Each run writes a pg_dump in custom format and a checksummed manifest into your bucket — plus a copy of your Storage files once you add its S3 keys on the project page. See the tree below for exactly what lands there.

06

Drills prove it restores (weekly on paid plans; once on Free)

Weekly on every paid plan — and once on Free, on your first backup — a drill restores your latest snapshot into a throwaway Postgres and verifies it: archive sha256, pg_restore completes, post-data objects (indexes and constraints) applied, table count matches, no missing tables, and populated tables are non-empty. Every drill produces a report, and failures alert you by email — so the day you need an actual restore, it’s a known quantity.

What lands in your bucket

<prefix>/<project>/<timestamp>/
  ├── dump.pgcustom              # pg_dump --format=custom (public schema by default)
  ├── storage/<bucket>/<key>     # your Storage files (if Storage keys are added)
  └── manifest.json              # schemas, tables, estimated row counts, file list, sizes + sha256

Plain pg_dump output and plain files — no proprietary format, nothing that needs us to read back.

One note on retention: the console rotates its snapshot records per your plan, but we never delete objects from your bucket — a backup tool holding delete permissions is a bigger risk than the storage bill. Old folders accumulate until a one-time lifecycle rule cleans them up; each destination guide (R2, S3, B2) shows the setup. Keep the expiry longer than your plan’s retention so a paused project can’t age out of its last good snapshot.