How to verify a Supabase restore

Choose the right Supabase restore path, investigate errors, and verify database, files, access, and configuration before treating a backup as recovered.

By Antoine RossPublished Facts verified

A restore message is not proof that your application is ready. First identify the type of backup and where it is being restored. Then verify the data, access rules, files, and application behavior in an isolated destination before changing production traffic.

Pick the restore path first

Supabase provides different workflows with different behavior:

  • Restore to a new project: for eligible physical backups or point-in-time recovery, Supabase creates a separate project with a database copy. The feature currently requires a paid plan and physical backups on the source; PITR is a separate add-on. The new project incurs its own resource costs. Restore to a new project
  • Manual logical backup and restore: use the Supabase CLI and PostgreSQL restore guide when you need a manual, inspectable workflow. Its documented procedure includes separate role, schema, and data dumps and a transactional restore that stops on errors. Follow its encryption and migration-history instructions when applicable.
  • Legacy downloadable Dashboard backup: the Dashboard backup guide applies to older projects still using logical backups. Do not assume the instructions for that file apply to a physical backup.

A physical restore to a new project copies the database, including enabled extensions that can run external operations. Supabase warns that copied cron jobs, webhooks, or wrappers can run immediately after the restore, with no option to pause or exclude them during that operation. If those side effects could send messages, charge customers, or alter external systems, use the documented logical workflow and inspect and disable or remove the risky definitions before they can run. A logical restore is not automatically isolated: review the dump and destination configuration before loading, ensure schedules, triggers, webhooks, and external credentials cannot reach live services, and verify those controls in the destination. If you cannot establish that boundary, stop and get expert or provider help. A logical restore does not automatically carry the encryption root key; follow Supabase's separate key instructions if Vault or encrypted columns are involved. Restore safety details, logical restore and encryption

Rehearse the chosen route

New-project physical restore. In the source project, open Database → Backups → Restore to a New Project. Select a backup, or an available PITR time before the incident. Review the new project's cost and the immediate side-effect warning above before starting. Wait for the destination to finish provisioning, then record the new project reference and recovery time. This route creates its own destination; it does not restore into an existing project. Isolate application traffic until the checks below pass. Supabase's new-project steps

Manual logical restore. If the source is accessible, follow the CLI backup and restore guide to make separate , , and files, then inspect and protect them as sensitive backups. Create a separate destination and check the target project reference and connection string before any restore. The guide's standard example restores the files in that order using psql --single-transaction and ON_ERROR_STOP=1; it also sets session_replication_role = replica before loading data. That suppresses triggers during the load, so verify required effects afterward rather than assuming they ran. Follow the guide's separate instructions for encryption keys, custom auth/storage changes, migration history, extensions, and Realtime when those apply. Before loading, inspect the dump and destination configuration and disable or remove every definition that could perform unwanted external work; verify the isolation controls actually hold. The replica setting for the data load does not itself guarantee cron, webhooks, functions, or later operations are isolated. Re-enable external jobs and integrations only after checking their destinations. Never paste a connection string containing a password into chat or a shared log.

Legacy Dashboard download. First confirm that the source uses the older downloadable logical backup; current physical backups are not that file. Download the backup and follow the Dashboard restore guide for the destination connection and import. Its full dump can report conflicts with managed schemas already present in a fresh project. Save the complete output and inspect each error; do not carry over the logical CLI example's assumptions without checking the file format. Restore Storage files separately.

Compare one important table

Suppose public.orders is critical. Compare an independently recorded count from the intended recovery point with the restored project. From the destination's SQL editor, confirm the project reference in the dashboard first, then run this read-only query:

select count(*) as restored_orders from public.orders;

If your independent count for the same point was 128 and the query returns 128, the count agrees. It does not prove the rows or permissions are correct. Check representative known order IDs and their ownership and statuses without exposing customer data in screenshots. A mismatch against today's live source may be expected if new orders arrived after the backup. Record the actual snapshot time and investigate unexplained differences before cutover. Repeat for critical tables and relationships rather than assuming every table has the same recovery behavior.

For authorization, sign in to a test deployment as an owner and verify that account's order is visible. Sign in as a second user and verify the first user's order is denied; test an anonymous session too. Use the same application/Data API path your users use. A successful query in the privileged SQL editor does not prove row-level security. Separately open a representative file through its intended authenticated path and compare its contents, not just the object metadata.

If the restore reports an error

Keep the source and backup unchanged. Record the method, source and destination project references, backup time, first complete error, and whether the destination was empty. Do not paste credentials or personal rows into a support request. A failed or interrupted restore can leave a destination unsuitable for a blind retry. Check what was applied, and follow the procedure for that specific path or start again in a fresh isolated destination after preserving the evidence.

For the older downloadable Dashboard full-dump method, Supabase says some object already exists errors arise because the destination already contains its managed auth and storage schemas. That is not a general license to ignore errors: inspect the exact object and subsequent errors, then verify the result. If the restore actually fails or the cause is unclear, contact Supabase support with redacted logs. Dashboard restore troubleshooting

For the CLI logical path, use the exact guide for your version. It documents particular role and ownership errors and targeted remedies. Do not remove every permission statement or turn off error stopping to make a run appear successful. The CLI guide's ON_ERROR_STOP and transaction settings serve a different workflow from the legacy full-dump guide; do not mix them without understanding the backup format and the consequences. CLI restore troubleshooting

Verify the recovered application

Before directing users to the new project, compare it with the intended recovery point. If the source has changed since that point, differences may represent expected data loss, not a faulty restore.

  1. Scope and time: record the backup or PITR time and compare critical table counts and selected records against a trustworthy snapshot from that same time where available. Check important relationships, constraints, indexes, functions, triggers, and extensions. A count alone does not prove row contents match.
  2. Permissions: inspect roles, grants, and row-level security policies. Test with representative accounts: an owner can access their own data, another user cannot, and anonymous access is denied where expected. Privileged database connections can bypass the access path your users take, so they are not a substitute for these tests.
  3. Auth: test sign-in, session refresh, password recovery, redirects, and enabled OAuth providers with test accounts. Reconfigure Auth settings and keys for the destination. Reset custom role passwords where the applicable backup method requires it. Supabase documents that daily backups do not retain custom role passwords. Backup limitations
  4. Files: confirm the actual contents of representative private and public objects, not just bucket rows or metadata. Database backups do not include Storage API objects. Restore or copy files separately and test access policies. Backup limitations
  5. Application and integrations: configure and test Edge Functions, secrets, API keys, Realtime settings and publications, external callbacks, and any scheduled work. For a new-project physical restore, Supabase lists these among settings or components needing separate attention. Ensure no test action can reach production payment, email, or webhook endpoints. New-project restore scope
  6. Migration history: compare the destination's applied migration history with the files you intend to use. A restored schema and an accurate migration history are separate checks; Supabase documents additional steps for preserving history in its logical workflow. Do not repair or mark history applied until you have verified what is actually present. CLI restore guide

Record the checks and remaining gaps. Only then plan a cutover, including how to stop writes, account for changes since the backup, and return to the source if verification fails. Keep the original recovery material until the new system has been independently verified.

For a Lovable Cloud export and the separate question of Drizzle migration history, see Fix Drizzle during a Lovable database move.