Restoring a project
How to restore one SupaHost project from a daily backup or a point in time, what happens step by step, how long the project is offline, and what to check afterwards.
A restore replaces one project's database with an earlier copy. It works on every plan from a daily backup, and on Pro and Business from any second inside the point-in-time window. Other projects on the instance keep running and aren't touched.
Start a restore
Only the instance owner can restore.
- Open Dashboard → your project → Backups.
- Either click Restore app-one on a backup in the list, or choose Restore to this point and pick a date and time (Pro and Business; see Point-in-time recovery).
- Type the project name to confirm.
The owner gets an email when the restore is done, or if it fails.
What happens
- Rebuild. The base backup, plus WAL up to your chosen time if you picked one, is replayed in a throwaway Postgres container with no network access. Your live project keeps serving traffic during this step, which is the longest one.
- Dump. Your project's database alone is dumped from that copy.
- Swap. The project's Auth, Data API and Storage services are stopped. The live database is renamed to
<db>_pre_restore_<timestamp>, for examplep_app_one_pre_restore_1762871400. - Load. The dump is restored into a fresh database under the project's normal name, and the services start again.
Your project is offline only during steps 3 and 4. Requests to the API return errors during that time, so plan for it as a short outage.
If any step fails, the rename is reverted and your project carries on with the database it had. If the SupaHost agent on the VM restarts in the middle, the restore is marked as failed ("Interrupted…"). A restore that runs longer than 6 hours is stopped.
How long it takes
SupaHost ran a restore drill on a Pro instance in November 2026, with identical data on every run:
| Database size | Total time | Project offline |
|---|---|---|
| 0.8 GB | about 4 minutes | about 55 seconds |
| 4.1 GB | about 12 minutes | about 4.5 minutes |
Time grows with database size and with how much WAL needs replaying. A point-in-time restore late in the day replays more WAL than one from just after a base backup. More on this in How long does a restore take?.
The previous database is kept for 3 days
The database you replaced isn't deleted straight away. It stays on the instance as <db>_pre_restore_<timestamp> for 3 days, then it's dropped. If you realise you restored to the wrong point, or need a few rows from the newer copy, email [email protected] within those 3 days.
A better habit: before restoring, export anything you might want from the current state. On Business you can do that yourself over SSH:
# Save the last day of orders to a local CSV before rewinding the project
echo "\copy (select * from public.orders where created_at > now() - interval '1 day') to stdout with csv header" \
| ssh [email protected] sudo supahost-psql app-one > orders-today.csv
On any plan, Create pg_dump on the Backups tab saves the whole current database first. See Exporting your data.
After a restore
Check these once the project is back:
- Storage files. Files aren't part of the restore.
storage.objectsnow matches the restored point, but the files on disk are as they were. Files deleted after that point are gone, and files uploaded after it exist on disk without a row. See A restore didn't bring back Storage files. - Cron jobs. Jobs are stored outside the project database, so a restore doesn't change them. A job you added after the restore point still exists and will run against the restored data. List them with
select jobname, schedule, active from cron.job;and see Stopping cron jobs on a restored project or branch. - Auth sessions. Users and refresh tokens are rolled back with the database. Sessions created after the restore point no longer exist, so some users will need to sign in again.
- Your app's caches. Anything your app cached from the newer data may now be out of step.
- Migrations. If you applied migrations after the restore point, they're rolled back too. Check
supabase_migrations.schema_migrationsand re-apply what you still want.
select version, name
from supabase_migrations.schema_migrations
order by version desc
limit 5;