On the Free plan there is no automatic Supabase backup: if a migration drops a table, the only copy is one you exported yourself. Pro keeps 7 days of daily backups, Team 14, and point-in-time recovery is a paid add-on. No plan’s database backup includes Storage files, and none is proven until you restore it.
What a Supabase backup is, and what each plan keeps
A Supabase backup is a copy of the project’s Postgres database that Supabase takes daily on paid plans and keeps for 7 days on Pro, 14 on Team and up to 30 on Enterprise. The Free plan has none, and no plan’s backup holds Storage files.
How long to keep copies, and where, is the same question on any host, and the database backup checklist for startups answers it; this page stays on what Supabase itself does and does not do.
Supabase runs its automatic backups once a day for every Pro, Team and Enterprise project, and lists them under Database > Backups in the dashboard. A Supabase free tier backup is the one you make yourself: for projects on the Free plan, Supabase’s docs recommend a regular export with the CLI’s db dump command and an off-site copy. Supabase does have backups of your data on a paid plan, taken daily, so check two things today: the plan name, and the newest date in that dashboard list.
| Plan | Daily backups | Retention | Point-in-time recovery | What a platform restore brings back |
|---|---|---|---|---|
| Free | None | None | Not available | Only what you exported yourself |
| Pro | Yes | 7 days | Paid add-on, at least Small compute | The database, not Storage objects |
| Team | Yes | 14 days | Paid add-on, at least Small compute | The database, not Storage objects |
| Enterprise | Yes | Up to 30 days | Paid add-on, at least Small compute | The database, not Storage objects |
Plans checked 2026-10-05 against Supabase’s backups docs. The prices of the plans themselves are not repeated here; what each Supabase plan costs keeps those current, and the only price on this page is the recovery add-on below.
Two details from the same docs page matter on restore day. Projects on recent Postgres versions use physical backups, which changes what you can download; the version cut-off is in the download method below. And daily backups do not store passwords for custom roles, so any custom role needs a new password after a restore.
Supabase PITR: what point-in-time recovery adds, and what it costs
Supabase PITR replaces daily backups with recovery to any chosen point, down to seconds, inside a 7, 14 or 28 day window. It is a paid add-on on Pro, Team and Enterprise, needs at least a Small compute add-on, and the 7-day line costs about $100 a month.
The gap it closes is the one Supabase’s docs name themselves: “Even with daily backups, you could still lose a day’s worth of data.” With PITR on, a bad afternoon migration can be undone to the moment before it ran, not to last night’s copy. Supabase lists point-in-time recovery pricing by retention window:
| Retention window | Hourly price | About per month |
|---|---|---|
| 7 days | $0.137 | about $100 |
| 14 days | $0.274 | about $200 |
| 28 days | $0.55 | about $400 |
Prices checked 2026-10-05 on Supabase’s PITR usage page. Supabase’s PITR pricing is hourly: you pay for every hour the add-on is active, a partial hour counts as a full one, and the add-on is not covered by the Spend Cap. For a sense of the total Supabase PITR cost, the docs’ own one-project example (a Pro project on Small compute with the 7-day window all month) comes to about $130 after a $10 compute credit.
A restore from PITR goes one of two ways. In place, the project is inaccessible while the restore runs, so plan for downtime; or through Restore to a New Project, which needs physical backups and creates a database-only copy next to the live one. The second path leaves production running while you look at the copy, and Supabase’s clone docs describe it as the safe way to get deleted rows back. Moving a handful of rows from that copy into the live project, without rolling everything else back, is its own procedure: how to undo an accidental deletion in Postgres.
We’d switch the add-on on once the app takes payments or holds data its customers create, because from then on a day of lost writes costs more than the add-on does. Before that, the daily backups plus your own dumps usually cover it.
What goes wrong when “backups are on”
Three gaps sit under the backups toggle, and each one stays hidden until the day you need the backup. Backups are also just one of the database checks a SaaS needs before customers rely on it; the rest are in the data consistency checklist for SaaS.
Storage files are not in the database backup
On every plan, database backups do not include objects you store through the Storage API, because the database only holds metadata about those objects. Restoring an old backup also does not bring back files deleted after it was taken. The result after a restore can be a documents table full of rows that point at files nobody can open.
A Supabase storage backup is therefore a separate job. Storage speaks S3, so Storage’s S3-compatible access lets an S3-compatible sync tool copy each bucket elsewhere, using an access key pair generated in the project settings plus the endpoint and region from the S3 configuration page. Those keys give full access to every bucket and bypass RLS policies, so they live in a server or CI secret and never in the app. Who can read those buckets in the first place is covered by the object storage security checklist.
Deleting the project deletes the backups
When a project is deleted, Supabase permanently removes all associated data, including the backups it holds, and its docs call the action irreversible. A paused project has its own limit: once paused for more than a year it can no longer be restored through Supabase Studio, though its database backup and Storage files can still be downloaded from Project Overview until the project is deleted. Either way, the only copy that survives a deleted project is one kept outside it. If that loss has already happened, start with what to do when the production database is deleted.
A backup nobody has restored
In our audits, one of the five apps we run ourselves had nothing in its repository that could take or restore a database backup, and nothing in its deploy applied migrations. Those five apps are part of a selected set from our June and July 2026 audits, so this is one case, not a measure of how common the gap is. That app’s full story belongs to how to self-host an app you exported.
A backup is a claim until a restore turns it into evidence. When a backup file will not restore, the cause is usually one of these, each named in Supabase’s backup and restore guide or the PostgreSQL manual: custom roles that come back with no password, an ownership or role-grant error involving supabase_admin or postgres in the dump, an extension the old database used that the new project has not enabled, or a Postgres version mismatch, since it is not guaranteed that pg_dump’s output can be loaded into a server of an older major version.
How to backup a Supabase project: four methods
A Supabase database is backed up in four ways: the dashboard’s daily backups on paid plans, a downloaded dashboard backup (older projects on logical backups only), the CLI’s db dump in three parts (roles, schema, data), or pg_dump against the connection string. Only the last two work on the Free plan.
The first needs nothing from you, the download is a click where it is still offered, and the last two are commands you or a scheduled job can run. Whichever you choose, a backup of a Supabase database only counts once it has been restored somewhere, which is the next section. The commands below are quoted from Supabase’s CLI reference and its backup and restore guide as they read on 2026-10-05, not run for this page.
Download a daily backup from the dashboard
Start in the browser: Database > Backups in the dashboard shows which daily backups exist and how old the newest one is. A Supabase backup download from that page is only offered to older projects that still use logical backups; projects on physical backups, the default on Postgres 15.8.1.079 and newer, are sent to the CLI method instead. Where the download exists, the file arrives gzipped with a .gz extension and unzips to a .backup file, and Supabase documents restoring it with psql into a new project or locally with supabase db start --from-backup.
supabase db dump: roles, schema and data
Supabase’s backup and restore guide takes the manual backup as a logical dump with the CLI, in three files: roles, schema and data. The CLI needs Docker Desktop, because supabase db dump runs pg_dump in a container.
supabase db dump --db-url [CONNECTION_STRING] -f roles.sql --role-only
supabase db dump --db-url [CONNECTION_STRING] -f schema.sql
supabase db dump --db-url [CONNECTION_STRING] -f data.sql --use-copy --data-only -x "storage.buckets_vectors" -x "storage.vector_indexes"
The three files matter because a plain Supabase dump holds neither data nor custom roles: the CLI reference says --role-only dumps only cluster roles, --data-only dumps only data records, and --use-copy writes copy statements in place of inserts. The default dump also skips Supabase-managed schemas such as auth and storage, so triggers or RLS policies you added to them have to be restored separately. The connection string comes from the Connect button in the dashboard, percent-encoded for --db-url; the guide uses the session pooler string by default and the direct one if your network has IPv6 or the project has the IPv4 add-on. Nothing in it depends on a paid feature, so the Supabase pg dump through the CLI works on every plan, Free included.
pg_dump against the connection string
Plain pg_dump works too: pg_dump’s documentation describes a custom format (-Fc) whose archive pg_restore can restore selectively, compressed by default. pg_dump copies one database only; roles live in the cluster, which is why the CLI method above takes them as a separate file. Supabase’s connection guide lists the direct connection for pg_dump and backup and restore; direct connections are on IPv6 unless the project has the IPv4 add-on, so from an IPv4-only network use the session pooler string, as the CLI method above does. Use a pg_dump at least as new as the project’s Postgres major version, since an older one refuses to dump a newer server.
A scheduled copy outside the project
The dashboard backups and PITR both live inside the project, so neither survives its deletion. A scheduled job, a CI workflow on a timer or a small server, can run the CLI dump each night and write the files to a bucket in another cloud or another account; that is the copy still there after the project is gone. Keep the database password in the job’s secret store, never in the repository. A Supabase backup on a self-hosted install is always this kind: Supabase’s self-hosting docs say some features of the managed platform aren’t available when self-hosting, managed backups and PITR among them, and list backups and disaster recovery among your responsibilities.
How to restore a backup into a new Supabase project, and prove it works
A Supabase backup is proven by restoring it somewhere that is not production and checking the data: row counts on the tables that matter, one real login, the Storage files the rows point to, and the time the whole restore took.
Run the test below once before launch and again whenever your backup method changes, so the restore half of Supabase backup and restore is known to work, not assumed. Supabase’s guide treats Restore to a new project and branching as separate flows from the manual logical restore, and any of them can be the target.
- 01 Restore into somewhere that is not production: a new project, a branch, or a local database started from the backup file. Never restore over the live project to test a backup. Write down the start time.
- 02 From a CLI dump, load the roles file before the schema and the data, in the order Supabase's backup and restore guide gives, and save the full command output, errors included.
- 03 Pick the five tables the business cannot lose, count their rows in the restored copy and in production, and write both numbers side by side.
- 04 Sign in to the restored copy as a real test user and note whether the login works and the user sees their own records.
- 05 Open three records that point to Storage files and check that each file loads. Expect them not to, unless the bucket copy was restored too.
- 06 Write down the end time. The gap between start and end is your honest recovery time, and the counts, the times and the date go in one note.
The local route, restoring a downloaded backup with the CLI, needs a Supabase Postgres version of at least 15.1.0.55, and a database started by the CLI is for inspection, not for production use. With a full dashboard dump, “object already exists” errors in a fresh project are expected, because the new project already has Supabase’s default schemas applied.
This check is also how the Production Hardening Sprint verifies deliverable 4.7, verified backups and restore: restore a backup into an isolated environment and check representative data integrity.
Where the sprint does this
If the app holds customer data, nobody has restored a backup yet, and a launch, an investor review or a first enterprise customer is close, start with a free audit: a video call where we go over your backup setup with you and agree what a first restore test should prove. In the sprint, our engineers verify automated backups, set retention, and perform a real restore test, one of its 123 deliverables. Hosting, paid tools, and API usage remain in your accounts, so a PITR add-on stays on your own Supabase bill. The work happens on your existing Supabase project, because your app’s current framework and hosting setup are the starting point.
Common questions about backing up and restoring Supabase
How do I export data from Supabase?
For the whole database, use the CLI’s three-part dump (roles, schema, data) or pg_dump against the connection string; both work on any plan, Free included. For a single table, pg_dump’s --table option dumps only the tables whose names match, and the custom format lets pg_restore pick items back out later.
How do I copy a Supabase project?
On a paid plan with physical backups, open the source project’s database backups page and choose the Restore to a New Project tab; Supabase creates a new project holding a database-only copy with the data, roles and Auth users. Storage files and bucket settings, Edge Functions, Auth settings and API keys, Realtime settings, extension settings and read replicas need reconfiguring, and the new project bills on its own. Enabled extensions such as pg_cron and pg_net do come across, and their jobs start running as soon as the restore completes. On the Free plan, create a new project and load a CLI dump into it with psql, as Supabase’s backup and restore guide shows.
Does Supabase offer a free tier for backups?
No. Supabase takes no daily backups of Free projects (it keeps a backup only so a paused project can be restored); its docs recommend exporting the data regularly with the CLI’s db dump command and keeping off-site backups. That same export runs on every plan, so on a paid plan it doubles as the copy that survives a deleted project.
How much does Supabase PITR cost?
About $100 a month for a 7-day window, $200 for 14 days and $400 for 28 days, charged by the hour at $0.137, $0.274 and $0.55, on top of the plan and at least a Small compute add-on. Those are Supabase’s prices as checked on 2026-10-05.
Has anyone ever restored your Supabase data?
A backup only counts once someone has brought it back, and stored files often sit outside the copy. On the audit, we talk through how your app's data is kept and how you would recover it after a bad change. Then you know which gap to close first.
Book a free audit →
Free · 30 minutes · No code access needed