ThisCalculator

Everyday

Supabase Backup Restore: 5 Failure Modes & Runbook

Updated · Standard formula, shown below

Supabase Backup Restore: 5 Failure Modes & Runbook

This article explains the five most common ways a Supabase backup restore can fail and provides a safe, step-by-step runbook for testing your restore process. You will learn what causes each failure, how to detect it before it matters, and how to practice restores without risking your production data.

Why Restore Testing Matters

Supabase offers automated daily backups for projects on the Pro plan and above, with point-in-time recovery (PITR) available as an add-on. However, having backups is not the same as being able to restore them. A backup that cannot be restored is worthless, and the only way to know yours works is to test it. Many teams discover too late that their backup was corrupt, incomplete, or incompatible with their current schema. The cost of an untested restore is downtime, data loss, and a very stressful incident.

Failure Mode 1: Corrupted or Incomplete Backup Files

The first and most common failure is a backup file that is corrupted or incomplete. Supabase stores backups as encrypted files in a separate storage service, and while the platform handles the encryption and retention, the file itself can be damaged during transfer or storage. You might see an error like “archive is not a valid database backup” or the restore process simply hangs. To catch this, you must download a backup and verify its integrity before you ever need it. For PostgreSQL dumps, you can run pg_restore --list file.dump to see if the archive is readable. For physical backups, check the file size and checksum against what Supabase reports. If you cannot list the contents, the backup is already unusable.

Failure Mode 2: Schema and Version Mismatch

Another frequent failure is trying to restore a backup into a database that has a different schema or a different PostgreSQL version. Supabase manages the database version for you, but if you have been running migrations, your current schema may have tables, columns, or constraints that did not exist when the backup was taken. Restoring a logical dump with pg_restore will fail if it tries to create a table that already exists, or if it references a type that has changed. Similarly, restoring a physical backup from an older PostgreSQL version into a newer one can fail due to internal format changes. The fix is to always restore into a fresh, empty database that matches the source version, and to apply your migrations after the restore, not before. Test this by creating a new Supabase project, restoring the backup there, and then running your migration scripts to see if they apply cleanly.

Failure Mode 3: Insufficient Permissions and Roles

Supabase projects come with a set of default roles and permissions, and your backup contains the definitions of those roles. When you restore into a new project, the roles may already exist with different passwords or privileges, causing conflicts. For example, the postgres role is always present, but the backup may try to alter it. More commonly, custom roles you created (like a read-only role for analytics) are not restored because the backup only includes the public schema and certain objects. If your application relies on those roles, it will fail after a restore. To avoid this, document all custom roles and their grants, and recreate them manually after a restore. During testing, compare the roles in the source and target databases with \du in psql to see what is missing.

Failure Mode 4: Large Database Timeouts and Resource Limits

Restoring a large database can exceed the time limits or resource constraints of the target project. Supabase has a maximum restore size and a timeout for the restore operation. If your database is several gigabytes, the restore may take longer than the allowed window, and the operation will be killed. You may see an error like “restore timed out” or the restore process just stops. The workaround is to split the restore into smaller chunks: restore the schema first, then the data, or use pg_restore with the --jobs flag to parallelize the load. For very large databases, consider using pg_dump with the --format=directory option, which allows you to restore tables individually. Always test with a representative sample of your data to estimate the time and adjust your approach.

Failure Mode 5: Point-in-Time Recovery (PITR) Gaps

Point-in-time recovery is a powerful feature, but it has its own failure modes. PITR relies on write-ahead log (WAL) archives, and if there is a gap in the WAL files, you cannot recover to a specific timestamp. Gaps can occur if the WAL archive is temporarily unavailable, or if the backup retention period is shorter than the PITR window. You might restore to a time that is actually several minutes before your target, losing recent transactions. To test PITR, pick a time when you know a specific change was made (like a test row inserted at 14:30), then restore to that exact time and verify the row exists. If it does not, your WAL archive is incomplete. Also, remember that PITR can only restore to a time within the backup retention window; you cannot go back further than your oldest backup.

Safe Restore Testing Runbook

Here is a step-by-step runbook to test your Supabase backups safely without risking production data.

  1. Create a staging project. In the Supabase dashboard, create a new project. This will be your restore target. Use the same region and PostgreSQL version as your production project.
  2. Download a recent backup. Go to your production project’s Backup section, find the latest backup, and download it. Note the file size and checksum.
  3. Verify the backup file. Run pg_restore --list backup.dump to confirm the archive is readable. If it fails, your backup is corrupt and you need to contact Supabase support or use an older backup.
  4. Restore the backup. In the staging project, use the Supabase dashboard to restore the downloaded backup. Alternatively, use the Supabase CLI or pg_restore directly. For a physical backup, you may need to use the dashboard’s restore feature.
  5. Check for errors. After the restore completes, check the logs for any warnings or errors. Common issues include missing roles, failed constraints, or truncated data.
  6. Verify data integrity. Run a few queries to compare row counts and sample data between production and staging. For example, SELECT count(*) FROM your_table; should match.
  7. Test your application. Point your application’s connection string to the staging project and run a smoke test. This ensures the restored database works with your code, not just that the data is present.
  8. Document the results. Record the time taken, any errors, and the steps you used. This documentation becomes your runbook for a real disaster.

Frequently Asked Questions

Can I restore a backup into the same project?

No, Supabase does not allow you to restore a backup into the same project because it would overwrite the current database. You must restore into a new project. This is a safety measure to prevent accidental data loss, but it means you need to have a spare project available in an emergency.

How long does a restore take?

It depends on the size of your database and the region. A small database (under 1 GB) might restore in a few minutes, while a large one (10+ GB) can take over an hour. Supabase does not provide a precise time estimate, so you should test with your own data. The restore time also counts against your project’s resource usage, which can affect performance.

What is the difference between a logical and a physical backup?

Logical backups (like pg_dump) contain SQL statements to recreate the schema and data. They are portable across PostgreSQL versions but slower to restore. Physical backups are file-level copies of the database directory, which are faster to restore but must match the exact PostgreSQL version and platform. Supabase uses physical backups for its automated daily backups, but you can also create logical backups manually.

Does restoring a backup affect my production database?

No, restoring a backup into a new project does not affect your production database. The restore process only writes to the target project. However, if you are restoring into a project that is already in use, it will overwrite that project’s data. Always use a dedicated staging project for testing.

Can I automate restore testing?

Yes, you can automate the process using the Supabase CLI or the Management API. You can write a script that creates a new project, downloads the latest backup, restores it, and runs integrity checks. This is a good practice to ensure your backups are always restorable. However, be aware that each new project incurs costs, so you may want to schedule tests periodically rather than daily.

What should I do if a restore fails?

First, check the error message. Common fixes include: using a fresh project, ensuring the backup file is not corrupt, and applying migrations after the restore. If the error is about permissions, recreate custom roles manually. If the restore times out, split it into smaller parts. If you cannot resolve the issue, contact Supabase support with the error log and your backup file details.

Related

Method: the standard formula for this calculation, rounded as each result states. See how the calculators work or report an error.