Skip to main content
RapidDev - Software Development Agency
supabase-tutorial

How to Restore a Supabase Backup

To restore a Supabase backup, use the point-in-time recovery feature in the Dashboard for Pro plan projects, or restore a pg_dump file using psql or pg_restore on the command line. Point-in-time recovery lets you restore to any second within the retention window. For manual backups, download the dump file from the Dashboard and restore it to a new or existing project using the direct database connection string.

What you'll learn

  • How to use point-in-time recovery on Supabase Pro plans
  • How to restore a pg_dump backup file using psql
  • How to restore selectively using pg_restore with custom-format dumps
  • How to verify data integrity after a restore
Book a free consultation
4.9Clutch rating
600+Happy partners
17+Countries served
190+Team members
Intermediate7 min read15-25 minSupabase Pro+ (point-in-time recovery), Free plan (manual pg_dump restore), PostgreSQL 15+March 2026RapidDev Engineering Team
TL;DR

To restore a Supabase backup, use the point-in-time recovery feature in the Dashboard for Pro plan projects, or restore a pg_dump file using psql or pg_restore on the command line. Point-in-time recovery lets you restore to any second within the retention window. For manual backups, download the dump file from the Dashboard and restore it to a new or existing project using the direct database connection string.

Restoring a Supabase Database Backup

Database disasters happen — accidental deletes, bad migrations, or corrupted data. Supabase provides two restoration paths: point-in-time recovery (PITR) for Pro and Enterprise plans, which lets you restore to any second within your retention window, and manual restoration from pg_dump files for all plans. This tutorial covers both methods, from clicking a button in the Dashboard to running pg_restore on the command line.

Prerequisites

  • A Supabase project with an existing backup (PITR or pg_dump file)
  • Supabase CLI installed for command-line restore
  • Your database connection string from Dashboard > Settings > Database
  • psql or pg_restore installed locally (included with PostgreSQL)

Step-by-step guide

1

Restore using point-in-time recovery in the Dashboard

For Supabase Pro and Enterprise plans, point-in-time recovery (PITR) lets you restore your database to any point within the retention period (7 days on Pro, 30 days on Enterprise). Go to the Supabase Dashboard > Settings > Database > Backups. Select the Point-in-Time tab. Choose the date and time you want to restore to, then click Restore. Supabase will create a new database state matching that exact point in time. This process can take several minutes depending on database size.

Expected result: Your database is restored to the selected point in time. All data changes after that point are removed.

2

Download a backup file from the Dashboard

Supabase creates daily automatic backups for Pro plans and above. Go to Dashboard > Settings > Database > Backups > Scheduled Backups tab. You will see a list of available backups with dates. Click Download on the backup you want to restore. For free plan projects, you need to create your own backups using pg_dump before you can restore. The downloaded file is a PostgreSQL dump that can be restored with psql.

typescript
1# If you need to create a manual backup first:
2pg_dump "postgresql://postgres.[ref]:[password]@aws-0-[region].pooler.supabase.com:5432/postgres" \
3 --clean \
4 --if-exists \
5 -F c \
6 -f backup_20260327.dump

Expected result: A backup dump file is saved locally or downloaded from the Dashboard.

3

Restore a SQL format backup with psql

If your backup is a plain SQL file (created with pg_dump without -F c), restore it using psql. Connect to your Supabase database using the direct connection string (port 5432, not the pooled port 6543) and pipe the SQL file into it. The --clean flag in the original dump means it will drop existing objects before recreating them. Make sure no other applications are actively writing to the database during the restore.

typescript
1# Restore a plain SQL backup
2psql "postgresql://postgres.[ref]:[password]@aws-0-[region].pooler.supabase.com:5432/postgres" < backup.sql
3
4# Or restore to a local Supabase instance for testing
5supabase start
6psql "postgresql://postgres:postgres@localhost:54322/postgres" < backup.sql

Expected result: The database schema and data are restored from the SQL backup file.

4

Restore a custom-format backup with pg_restore

Custom-format dumps (created with pg_dump -F c) offer more flexibility. Use pg_restore to restore the entire dump or selectively restore specific tables. The --clean flag drops existing objects before restoring, and --if-exists prevents errors if an object does not exist. Use the -t flag to restore a single table, which is useful when you only need to recover specific data.

typescript
1# Restore entire database from custom-format dump
2pg_restore \
3 --clean \
4 --if-exists \
5 -d "postgresql://postgres.[ref]:[password]@aws-0-[region].pooler.supabase.com:5432/postgres" \
6 backup_20260327.dump
7
8# Restore only a specific table
9pg_restore \
10 -t products \
11 --data-only \
12 -d "postgresql://postgres.[ref]:[password]@aws-0-[region].pooler.supabase.com:5432/postgres" \
13 backup_20260327.dump
14
15# List contents of a dump file (inspect before restoring)
16pg_restore --list backup_20260327.dump

Expected result: The database or specific tables are restored from the custom-format dump file.

5

Verify data integrity after the restore

After restoring, verify that the data is correct and complete. Check row counts for critical tables, verify that RLS policies are in place, and test that your application can connect and query data normally. Compare the restored state against known data points — for example, check whether a specific user record exists or whether the total order count matches expectations. Also verify that functions, triggers, and indexes were restored correctly.

typescript
1-- Check row counts for critical tables
2SELECT 'users' AS table_name, count(*) FROM auth.users
3UNION ALL
4SELECT 'profiles', count(*) FROM public.profiles
5UNION ALL
6SELECT 'orders', count(*) FROM public.orders;
7
8-- Verify RLS is enabled
9SELECT tablename, rowsecurity
10FROM pg_tables
11WHERE schemaname = 'public';
12
13-- Check that RLS policies exist
14SELECT tablename, policyname
15FROM pg_policies
16WHERE schemaname = 'public';

Expected result: Row counts match expected values, RLS is enabled on all tables, and policies are in place.

Complete working example

restore-supabase-backup.sh
1#!/bin/bash
2# Supabase Database Restore Script
3# Usage: ./restore-supabase-backup.sh <backup-file> <connection-string>
4
5set -e
6
7BACKUP_FILE=$1
8CONNECTION_STRING=$2
9
10if [ -z "$BACKUP_FILE" ] || [ -z "$CONNECTION_STRING" ]; then
11 echo "Usage: ./restore-supabase-backup.sh <backup-file> <connection-string>"
12 echo "Example: ./restore-supabase-backup.sh backup.dump 'postgresql://postgres.[ref]:[pass]@host:5432/postgres'"
13 exit 1
14fi
15
16if [ ! -f "$BACKUP_FILE" ]; then
17 echo "Error: Backup file '$BACKUP_FILE' not found"
18 exit 1
19fi
20
21echo "=== Supabase Backup Restore ==="
22echo "Backup file: $BACKUP_FILE"
23echo ""
24
25# Detect file format
26FILE_TYPE=$(file "$BACKUP_FILE")
27
28if echo "$FILE_TYPE" | grep -q "PostgreSQL"; then
29 echo "Detected custom-format dump. Using pg_restore..."
30 echo "Listing dump contents..."
31 pg_restore --list "$BACKUP_FILE" | head -20
32 echo "..."
33 echo ""
34 echo "Restoring database..."
35 pg_restore \
36 --clean \
37 --if-exists \
38 --no-owner \
39 --no-privileges \
40 -d "$CONNECTION_STRING" \
41 "$BACKUP_FILE" 2>&1 || true
42else
43 echo "Detected SQL format dump. Using psql..."
44 psql "$CONNECTION_STRING" < "$BACKUP_FILE"
45fi
46
47echo ""
48echo "=== Verifying restore ==="
49psql "$CONNECTION_STRING" -c "
50SELECT schemaname, tablename, rowsecurity
51FROM pg_tables
52WHERE schemaname = 'public'
53ORDER BY tablename;"
54
55echo ""
56echo "Restore complete. Verify data in Supabase Dashboard."

Common mistakes when restoring a Supabase Backup

Why it's a problem: Using the pooled connection string (port 6543) for pg_restore instead of the direct connection (port 5432)

How to avoid: Always use the direct connection string from Dashboard > Settings > Database for pg_dump and pg_restore operations.

Why it's a problem: Restoring a backup without first backing up the current state of the database

How to avoid: Always create a fresh pg_dump of the current database before restoring. This gives you a way to revert if the restored state is not what you expected.

Why it's a problem: Restoring a full database dump when only a single table needs recovery, overwriting good data

How to avoid: Use pg_restore with -t tablename --data-only to selectively restore just the table you need without affecting other tables.

Best practices

  • Always back up the current database state before performing any restore operation
  • Test restores on a local Supabase instance with supabase start before applying to production
  • Use custom-format dumps (-F c) for backups because they support selective table restoration
  • Verify RLS policies and row counts after every restore to ensure data integrity
  • Use point-in-time recovery for recent data loss on Pro plans instead of manual restore
  • Keep a restore verification checklist with critical data points to check after every restore
  • Document the restore procedure for your team so anyone can perform it in an emergency

Still stuck?

Copy one of these prompts to get a personalized, step-by-step explanation.

ChatGPT Prompt

I accidentally deleted important data from my Supabase database. Walk me through restoring from a pg_dump backup file using pg_restore, including how to selectively restore just one table without overwriting other data. Also explain how point-in-time recovery works on Supabase Pro plans.

Supabase Prompt

Write a shell script that restores a Supabase database from a pg_dump file. The script should detect whether the file is SQL or custom format, restore accordingly, and then verify the restore by checking table counts and RLS policy status.

Frequently asked questions

Is point-in-time recovery available on the free plan?

No. Point-in-time recovery requires a Pro plan or higher. Free plan users must create manual backups with pg_dump and restore from those files.

How far back can I restore with point-in-time recovery?

Pro plans have a 7-day retention window. Enterprise plans have a 30-day retention window. You can restore to any second within that window.

Can I restore a backup to a different Supabase project?

Yes. Use pg_restore or psql with the connection string of the target project. This is useful for creating a staging environment from production data.

Will restoring a backup affect my RLS policies?

If you used pg_dump without --data-only, the dump includes RLS policies and they will be restored. If you used --data-only, only data is restored and existing policies remain unchanged.

How long does a restore take?

It depends on database size. Small databases (under 1 GB) typically restore in under 5 minutes. Larger databases can take 15-30 minutes or more. Point-in-time recovery may take longer depending on the amount of WAL data to replay.

Can I restore just one table from a backup?

Yes, but only from custom-format dumps (created with pg_dump -F c). Use pg_restore -t tablename --data-only to restore just the data for that table. Plain SQL dumps do not support selective restore.

Can RapidDev help with database recovery and restore procedures?

Yes. RapidDev can set up automated backup schedules, write restore scripts, test recovery procedures, and help recover from data loss incidents. They can also configure point-in-time recovery and verify data integrity after restores.

RapidDev

Talk to an Expert

Our team has built 600+ apps. Get personalized help with your project.

Book a free consultation

Need help with your project?

Our experts have built 600+ apps and can accelerate your development. Book a free consultation — no strings attached.

Book a free consultation

We put the rapid in RapidDev

Need a dedicated strategic tech and growth partner? Discover what RapidDev can do for your business! Book a call with our team to schedule a free, no-obligation consultation. We'll discuss your project and provide a custom quote at no cost.