GUIDES / SUPABASES3

How to back up Supabase Postgres to Amazon S3

RESTORE-TESTED · ENCRYPTED · IN A BUCKET YOU OWN

Supabase keeps your database running, but its snapshots live in the same account and region as the database itself. An off-site copy in your own Amazon S3 bucket protects you from the failures the platform can't: a bad migration, a locked account, or a compliance question you need a real answer to. Here's how to set it up in a few minutes — and, crucially, how to know the backup actually restores.

Step 1 — Get your Supabase connection string

Supabase dashboard → Project Settings → Database → Connection string. Choose the URI tab.

Use the direct connection or the session-mode pooler (port 5432). Do not use the transaction-mode pooler (port 6543) — it doesn't support the session state pg_dump needs, and your backup will fail. If your network is IPv4-only and the direct host won't resolve, the session pooler is the reliable choice.

A read-only role is all you need. The exact CREATE ROLE SQL is on the security page.

Step 2 — Create a Amazon S3 bucket and access keys

  1. In the S3 console, create a bucket (block all public access — backups should never be public).
  2. Create an IAM user with programmatic access and the S3 policy above.
  3. Copy the access key ID and secret access key.

Create an IAM user with programmatic access and a policy granting s3:PutObject, s3:GetObject, s3:DeleteObject, and s3:ListBucket on the bucket. Use that user's access key ID and secret.

Endpoint: (leave blank — AWS default)
Region:   your bucket's region, e.g. us-east-1
Bucket:   your-backup-bucket

Step 3 — Connect it to OffsiteDB

Paste the Supabase connection string, add Amazon S3 as your destination with the bucket and keys from Step 2, and choose a schedule (hourly to daily). OffsiteDB tests the connection, then runs pg_dump, gzips and seals the artifact with AES-256-GCM, and ships it to your bucket. The public schema holds your application data. The auth and storage schemas are managed by Supabase and aren't readable by a normal role — include them only if you connect with your full postgres credentials.

Step 4 — Know it restores (the part everyone skips)

Every snapshot is restore-drilled: OffsiteDB restores it into a throwaway Postgres cluster and counts the rows before marking it sealed. When you need it back, every artifact is a standard custom-format dump:

gunzip -c supabase-db_2026-06-09.dump.gz \
  | pg_restore -d "$NEW_DATABASE_URL" --clean --if-exists

You also get a monthly Restore Drill Report with tested restore times — the document you forward when someone asks “are your backups tested?”

FAQ

Does this work with Supabase's free tier?
Yes. OffsiteDB connects with any standard Supabase connection string regardless of tier. Supabase Postgres runs Postgres 15, which is fully supported.
What permissions does the backup need on Supabase?
A read-only role is enough — OffsiteDB only ever runs pg_dump and never needs write access. The public schema holds your application data. The auth and storage schemas are managed by Supabase and aren't readable by a normal role — include them only if you connect with your full postgres credentials.
Where exactly does my data end up?
In your own Amazon S3 bucket, encrypted with AES-256-GCM before it leaves the backup worker. OffsiteDB never holds the only copy — if you ever leave, your backups are standard pg_dump archives you can restore without us.
Can I just run pg_dump in a cron job instead?
You can — but a cron job doesn't prove the dump restores, alert you when it silently stops, or hand you a tested-restore report for a security review. OffsiteDB restore-drills every snapshot into a real Postgres cluster, which is the part that matters when you actually need it.

Related guides