The short answer
Stop the agent, then restore a backup into a new Supabase project at a point just before the delete, and copy the missing rows back into production. Supabase’s paid plans can restore a physical backup, or an exact point in time if Point-in-Time Recovery is on, into a separate project that is independent of the source.2 That keeps every good write made since the backup. Restoring over the live project is simpler, but the project is inaccessible while it runs and you lose what was written after the restore point.1
On the Free plan, Supabase recommends exporting your data yourself; if you have no export, there may be nothing to restore from.1
Deedglass
A database change, checked and put back
-
1The agent’s change
Change order 42
UPDATE orders … WHERE id = 42
The agent: “1 row updated” -
2What the database really did
301 rows
A hidden trigger changed 300 more
Doesn’t match -
3Put back
301 rows restored
Signed off by a person
Matches
First: stop the agent and keep the evidence
Before restoring anything, make sure the agent can’t keep going. Revoke the key or role it used, close the session, and save its transcript and the database logs. Our first-hour checklist covers the order. If the agent held a secret or service_role key, it was past every policy you wrote; the service_role post explains why and how to rotate it.
Then write down two facts. The time of the delete, as precisely as you can (the agent’s transcript or the Postgres logs usually have it). And what it touched: which tables, roughly which rows.
What your plan can restore
| Plan | Daily backups | Point-in-time recovery | Restore into a new project |
|---|---|---|---|
| Free | Not stated; Supabase recommends regular exports1 | No | No (paid plans only)2 |
| Pro | Last 7 days1 | Add-on, needs at least a Small compute1 | Yes2 |
| Team | Last 14 days1 | Add-on1 | Yes |
| Enterprise | Up to 30 days1 | Add-on1 | Yes |
Point-in-time recovery restores to any chosen point with granularity down to seconds, priced for 7, 14 or 28 days of retention.1 Without it, you pick the closest daily backup before the delete and accept whatever was written between that backup and the delete.
Two ways back
Restore over the project. Pick a backup or a point in time in the dashboard. Simple, and right when the agent damaged so much that the whole database is suspect. The costs: the project is inaccessible during the restore, so plan for downtime, and with daily backups you should “consider how many days of data you might lose.”1
Restore beside it, then copy back. Restore to a new project, find the deleted rows there, and insert them into production. Production stays up and keeps every write since. The new project copies the schema, data, roles and auth users, but not storage objects, Edge Functions, auth settings, API keys or database extension settings.2 For pulling rows out, that’s all you need.
One caution from Supabase’s docs: because the restore is binary, enabled extensions such as pg_cron or pg_net can start jobs as soon as the new project is up, and there’s no way to pause them during the restore.2 If a cron job sends emails or calls webhooks, the restored copy may send them again. Check what’s scheduled, and disable it in the copy the moment it’s ready, or use a logical restore with the CLI instead.
Worked example: copy back only the deleted rows
We ran this locally on PostgreSQL 18.6 with two databases standing in for the two projects: prod, where an agent deleted 300 of 500 orders, and restored, the copy from before the delete.
In production, the damage:
Code What the screen or file shows, copied as is.
DELETE 300
From the restored copy, export just the missing rows to a file:
Code A database command in SQL. The text around it says what it does.
\copy (select * from orders where id > 200) to 'orders.csv' csv
Code What the screen or file shows, copied as is.
COPY 300
In production, load them into a temporary table and insert only rows that aren’t already there, in one transaction:
Code A database command in SQL. The text around it says what it does.
begin;
create temp table recovered (like orders including all);
\copy recovered from 'orders.csv' csv
insert into orders select * from recovered on conflict (id) do nothing;
select count(*) from orders;
commit;
Code What the screen or file shows, copied as is.
COPY 300
INSERT 0 300
count
-------
500
Three choices in that script matter on a real project:
on conflict (id) do nothingskips any row that came back some other way, so the script is safe to re-run.- A temporary table lets you inspect what you’re about to insert before the
insertruns. - One transaction means either every row returns or none do.
For a whole table, pg_dump --data-only -t <table> against the restored project’s connection string does the same export in one step. It dumps only the data, not the schema.3 When -t is used, pg_dump doesn’t dump the objects the table depends on, so load the output into a database that already has the schema.3
If the agent changed rows rather than deleting them, the same method works with insert ... on conflict (id) do update, but think first: a row the agent “damaged” may also have had a legitimate update since. Compare before you overwrite.
What a restore won’t bring back
- Storage files. Database backups don’t include objects stored through the Storage API, and restoring an old backup doesn’t restore objects you deleted after that backup.1
- Side effects outside the database. Emails sent, webhooks fired and payments made by the agent stay done.
- Writes after the restore point, if you restore over the project instead of beside it.
Set this up before you need it
- On Free, schedule your own exports with the Supabase CLI’s
db dump.1 - On Pro and above, decide whether Point-in-Time Recovery is worth its cost for the tables an agent can reach.
- Give agents a development project or branch, not production. Our Supabase MCP checklist covers the settings.
- Keep a record of what each agent session changed, so “which rows?” has an answer. Change-level undo is in undo for agent sessions.
Before connecting an agent at all, paste the agent’s MCP config into the check page or run npx deedglass scan (how the grade works) to see whether it can read a database URL without a prompt. To try the checks in your browser without installing anything, open the playground.
Questions people ask
Can Supabase restore a single table?
The backups page doesn’t describe single-table restores. Restoring into a new project and copying the table back, as above, gets you the same result without touching the rest of production.2
Does a Supabase restore cause downtime?
Restoring over the project does: the project is inaccessible during the process.1 Restoring into a new project leaves the original alone.2
Are Supabase Storage files included in backups?
No. Database backups don’t include objects stored through the Storage API.1
Written with AI assistance and checked against our claims register.