Skip to content

Supabase Database Backups — Automatic and Manual Backup Strategies

DodaTech Updated 2026-06-28 5 min read

In this tutorial, you will learn about Supabase Database Backups. We cover key concepts, practical examples, and best practices to help you master this topic.

Supabase provides automatic daily backups for all projects, with point-in-time recovery (PITR) on paid plans, manual backup downloads via pg_dump, and the ability to clone databases between projects.

What You'll Learn

By the end of this lesson you will understand Supabase's backup schedule, perform manual backups with pg_dump, restore from backups, enable point-in-time recovery, and implement a custom backup Strategy.

Why It Matters

Data loss can destroy a business. Understanding Supabase's backup options ensures you can recover from accidental deletions, data corruption, or application bugs without losing customer data.

Real-World Use

DodaZIP runs a nightly pg_dump backup to a separate encrypted storage bucket. In addition, Supabase's automated backups provide daily snapshots that can be restored with a single click in the dashboard.

flowchart LR
    DB[(PostgreSQL)] -->|Daily automatic| B1[Supabase Backup Storage]
    DB -->|PITR logs| B2[WAL Archive]
    DB -->|Manual pg_dump| B3[Custom Storage]
    B1 -->|Restore| DB
    B2 -->|Point-in-time| DB
    B3 -->|Import| DB
    style DB fill:#3ecf8e,color:#fff

Automatic Backups

Supabase automatically backs up your database on a schedule.

# automatic_backups.py
# Understanding Supabase automatic backup schedule

def backup_schedule():
    schedules = {
        "Free Tier": "Daily full backup, 7-day retention",
        "Pro Plan": "Daily full backup, 14-day retention",
        "Team Plan": "Daily full backup, 30-day retention",
        "Enterprise": "Custom backup schedule and retention",
    }
    
    print("Automatic Backup Schedule:")
    for plan, schedule in schedules.items():
        print(f"  {plan:15s} | {schedule}")
    
    print()
    print("Backup content:")
    print("  - Full database dump (all tables, indexes, functions)")
    print("  - Does NOT include storage files or auth config")
    print("  - Backups stored in Supabase-managed storage")

backup_schedule()

Manual Backups with pg_dump

Download a full database backup using PostgreSQL tools.

# Get your database connection string from Supabase Dashboard:
# Settings > Database > Connection string (URI)

# Download full database backup
pg_dump "postgresql://postgres:password@db.example.supabase.co:5432/postgres" \
  --format=custom \
  --file=supabase-backup.dump

# Download as plain SQL
pg_dump "postgresql://postgres:password@db.example.supabase.co:5432/postgres" \
  --format=plain \
  --file=supabase-backup.sql

# Compress the backup
gzip supabase-backup.dump
# manual_backup.py
# Manual backup process

def manual_backup_steps():
    print("Manual Backup Steps:")
    print()
    print("1. Get database connection string from Settings > Database")
    print("2. Run pg_dump with the connection string")
    print("3. Choose format: custom (restorable) or plain (readable)")
    print("4. Compress the output file")
    print("5. Store in a secure, separate location")
    print()
    print("Security notes:")
    print("  - Backup files contain ALL database data")
    print("  - Encrypt backup files before storing externally")
    print("  - Never commit backup files to version control")

manual_backup_steps()

Point-in-Time Recovery

Restore to any point within the retention period.

# pitr.py
# Point-in-time recovery concept

def pitr_explanation():
    print("Point-in-Time Recovery (PITR):")
    print()
    print("Available on: Pro plan and above")
    print("Retention: Up to 7 days (Pro)")
    print()
    print("How it works:")
    print("  1. Supabase takes periodic base backups")
    print("  2. WAL (Write-Ahead Log) files are archived continuously")
    print("  3. You can restore to ANY point in time")
    print("  4. WAL files contain every database change")
    print()
    print("Use PITR when:")
    print("  - Accidental DELETE or UPDATE without WHERE clause")
    print("  - Schema migration error")
    print("  - Data corruption from application bug")
    print("  - Ransomware or malicious data modification")

pitr_explanation()

Restoring a Backup

Restore your database from a backup.

# In Supabase Dashboard:
# 1. Go to Database > Backups
# 2. Click "Restore" on the backup you want
# 3. Confirm the restoration
# 4. Wait for the process to complete

# For manual restore with pg_restore:
pg_restore --clean --if-exists \
  --dbname "postgresql://postgres:password@db.example.supabase.co:5432/postgres" \
  supabase-backup.dump
# restore_checklist.py
# Restoration checklist

def restore_checklist():
    print("Restoration Checklist:")
    print()
    print("Before restore:")
    print("  [ ] Notify users of scheduled downtime")
    print("  [ ] Take a current backup (in case you need to revert)")
    print("  [ ] Verify the backup file is not corrupted")
    print("  [ ] Check backup timestamp matches expected data state")
    print()
    print("During restore:")
    print("  [ ] The database is unavailable during restore")
    print("  [ ] Do not make any changes to the database")
    print("  [ ] Monitor the restore progress")
    print()
    print("After restore:")
    print("  [ ] Verify data integrity with test queries")
    print("  [ ] Check application connectivity")
    print("  [ ] Notify users that service is restored")

restore_checklist()

Common Mistakes

  1. Only relying on automatic backups: Automated backups are a safety net, but manual backups before major changes give you extra protection.

  2. Not testing backups: A backup that cannot be restored is worthless. Test your restore Process regularly.

  3. Storing backups in the same project: If the project is compromised, backups stored within it are also lost. Export backups to external storage.

  4. Forgetting storage files: Database backups do not include files in storage buckets. Back up storage files separately.

  5. Restoring without notification: Restoring a database with no warning can cause data loss for users who made changes after the backup timestamp.

Practice Questions

  1. How often does Supabase automatically back up databases? Daily, with retention varying by plan (7 to 30 days).

  2. What tool do you use for manual database backups? pg_dump for export and pg_restore for import.

  3. What is point-in-time recovery? The ability to restore to any specific moment within the retention period using WAL archives.

  4. Does the database backup include storage files? No. Database backups only include the PostgreSQL database, not files in storage buckets.

  5. Challenge: Create a backup automation script that runs pg_dump, compresses the output, encrypts it with GPG, and uploads it to an S3-compatible storage bucket.

FAQ

How long does a restore take?

Restore time depends on database size. A 1 GB database typically takes 5-15 minutes.

Can I download backups manually?

Yes. Use pg_dump via the connection string from Settings > Database.

Does PITR require additional configuration?

No. PITR is configured in the Dashboard and enabled automatically on Pro plans.

Can I restore to a different project?

Yes. Use pg_restore to import a backup into any PostgreSQL database, including another Supabase project.

What is the difference between custom and plain format?

Custom format (.dump) is compressed and supports selective restore. Plain format (.sql) is human-readable SQL.

Mini Project

Create a backup automation script that:

  1. Takes a pg_dump of the Supabase database
  2. Compresses it with gzip
  3. Adds a timestamp to the filename
  4. Uploads it to a Supabase storage bucket
  5. Cleans up backups older than 30 days
import subprocess
import datetime
import os

def backup_database():
    timestamp = datetime.datetime.now().strftime("%Y%m%d_%H%M%S")
    filename = f"backup_{timestamp}.dump.gz"
    
    print(f"Starting backup: {filename}")
    
    # Step 1: pg_dump
    print("Step 1: Running pg_dump...")
    # subprocess.run(["pg_dump", "--format=custom", "-f", f"backup_{timestamp}.dump", conn_string])
    
    # Step 2: Compress
    print("Step 2: Compressing backup...")
    # subprocess.run(["gzip", f"backup_{timestamp}.dump"])
    
    # Step 3: Upload to storage
    print("Step 3: Uploading to storage bucket...")
    
    # Step 4: Cleanup old backups
    print("Step 4: Cleaning backups older than 30 days...")
    
    print(f"Backup complete: {filename}")

backup_database()

What's Next

Next: Supabase Migrations for schema version control.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro