How to restore a Supabase project from a SQL backup
A step-by-step walkthrough of restoring a .sql.gz backup into a new or existing Supabase project — including troubleshooting, verification, and audit documentation.

When You Need This Guide
Your production database is gone. Maybe a migration went wrong. Maybe someone ran DROP TABLE. Maybe your Supabase project was deleted. You have a .sql.gz backup in your Google Drive from Supakeep. Now what?
This guide walks through the full restore process — from downloading the backup to verifying the restored data to documenting the test for compliance.
Source: [Supabase Docs — Backup and Restore using the CLI](https://supabase.com/docs/guides/platform/migrating-within-supabase/backup-restore)
Prerequisites
Before you start, you need:
- 1A
.sql.gzbackup file (from Supakeep's Google Drive folder) - 2A fresh Supabase project (create one in the dashboard — never restore to production)
- 3The
psqlcommand-line tool installed locally - 4Your new project's connection string (found in Dashboard > Settings > Database)
Step 1: Download the Backup
Backup folder structure (Google Drive):
supabackups/
|__ db_2026-07-30.sql.gz <- Database dump
|__ storage_2026-07-30.tar <- Storage objects
|__ auth_2026-w30.json.gz <- Auth data
|__ edge_2026-w30.zip <- Edge functionsDownload the db_*.sql.gz file for the date you want to restore to. If you also have storage and auth backups, download those too — you'll need them for a complete restore.
Step 2: Create a Fresh Supabase Project
Never restore to your production database. Always create a new project for testing.
- 1Go to https://supabase.com/dashboard
- 2Click "New Project"
- 3Choose a name like
restore-test-2026-07 - 4Select the same region as your original project
- 5Set a strong database password
- 6Wait for the project to provision (2-3 minutes)
Step 3: Decompress and Restore
# Decompress the backup
gunzip db_2026-07-30.sql.gz
# Restore to the new project
psql "postgresql://postgres:YOUR_PASSWORD@db.YOUR_REF.supabase.co:5432/postgres" \
-f db_2026-07-30.sqlRestore output:
SET
CREATE TABLE
CREATE TABLE
ALTER TABLE
COPY 10000
COPY 5000
CREATE INDEX
...
(no errors = success)If you see COPY X lines with numbers, data is being inserted. If you see errors, check the troubleshooting section below.
Step 4: Restore Storage Objects (If Applicable)
If your backup includes a storage_*.tar file, you need to upload the files back to your new project's storage buckets:
# Extract storage archive
tar -xf storage_2026-07-30.tar
# Upload files via the Supabase Storage API
# (Use the Supabase CLI or SDK for this step)This step is only needed if your app uses Supabase Storage for user uploads. Without this, storage URLs will return 404.
Step 5: Verify the Restore
-- Check table row counts
SELECT 'users' as table, count(*) FROM users
UNION ALL
SELECT 'posts', count(*) FROM posts
UNION ALL
SELECT 'orders', count(*) FROM orders;
-- Check RLS policies are intact
SELECT tablename, policyname, cmd
FROM pg_policies
WHERE schemaname = 'public';
-- Check roles exist
SELECT rolname FROM pg_roles
WHERE rolname IN ('anon', 'authenticated', 'service_role');If all row counts match, RLS policies are present, and roles exist — your restore is successful.
Step 6: Document for Compliance
If you're restoring as part of a compliance audit (SOC 2, ISO 27001), document the test:
Restore Test Record
Date: 2026-07-30
Backup file: db_2026-07-30.sql.gz
Target project: restore-test-2026-07
Result: SUCCESS
Rows restored: 17,500 (users: 10k, posts: 5k, orders: 2.5k)
RLS policies: 3 verified intact
Roles: anon, authenticated, service_role present
Verified by: [Your name]Screenshot the verification queries and attach to your audit evidence file. This is the documentation auditors look for.
Source: [Konfirmity — SOC 2 Backup And Recovery](https://www.konfirmity.com/blog/soc-2-backup-and-recovery-for-soc-2)
Troubleshooting
| Error | Cause | Solution |
|---|---|---|
permission denied for table | Missing role permissions | Recreate roles: CREATE ROLE anon; CREATE ROLE authenticated; |
relation already exists | Tables exist in target | Use --clean flag or restore to empty project |
role does not exist | Roles not in dump | Manually create Supabase roles before restore |
COPY failed | Data type mismatch | Check if backup was from a different Postgres version |
syntax error | Incompatible Postgres version | Use the same or newer Postgres version for restore |
- 1
Get a clean target
Create a fresh Supabase project or reset the existing database.
- 2
Fetch the dump
Download the .sql backup and verify its size and checksum.
- 3
Restore roles first
Apply roles and grants before data so RLS policies attach correctly.
- 4
Load schema and data
Run psql against the connection string and watch for errors.
- 5
Re-upload storage objects
Database dumps only carry file metadata, not the files.
- 6
Verify
Spot-check row counts, sign in as a real user, and confirm RLS behaves.
Related reading: Supabase backup best practices for small teams and pg_dump + GitHub Actions: the free way, and the 5 things it misses.
Frequently asked questions
It depends on database size. A small database (under 100MB) typically restores in 2-5 minutes. Larger databases (1GB+) can take 15-30 minutes or more. The `psql` command shows progress as it processes each table.
You can, but it's risky. Restoring to production can overwrite live data. Always restore to a fresh project first, verify the data, then switch your app's connection string if everything looks correct.
Standard pg_dump may not include global roles. You'll need to manually create Supabase's roles (anon, authenticated, service_role) before restoring data. Supakeep's auth backup artifact includes this information.
Yes. Database backups only contain metadata about storage objects, not the files themselves. If your app uses Supabase Storage, you need to restore both the database dump and the storage archive.
Run the restore to a test project, verify row counts and RLS policies with SQL queries, screenshot the results, and record the date, backup file, target project, and verification results. See Step 6 above for a template.
Check the troubleshooting table above. Common issues include missing roles, incompatible Postgres versions, and existing tables in the target project. Most errors have straightforward fixes documented in PostgreSQL's psql guide.