[{"data":1,"prerenderedAt":389},["ShallowReactive",2],{"blog-en-ai-agent-deleted-my-database":3},{"id":4,"title":5,"body":6,"category":349,"cover":350,"coverAlt":350,"description":351,"draft":352,"extension":353,"faq":354,"image":370,"keywords":371,"meta":377,"navigation":378,"ogTitle":379,"path":380,"published":381,"seo":382,"stem":383,"tldr":384,"updated":381,"__hash__":388},"blog_en\u002Fblog\u002Fai-agent-deleted-my-database.md","An AI agent deleted my Supabase data. What can I recover?",{"type":7,"value":8,"toc":336},"minimark",[9,13,16,19,24,27,39,42,46,49,52,55,58,61,65,68,71,74,83,87,90,199,207,211,214,217,223,226,229,233,236,239,242,245,250,254,257,260,263,282,297,304,308,328],[10,11,12],"p",{},"You asked the agent to tidy up some test rows, or to fix a migration that would\nnot apply. It wrote the SQL itself, ran it against the project your live app\nuses, and reported that it was done. The app still loads. The table is empty.",[10,14,15],{},"When an AI agent has deleted data from your database, what you can recover was\ndecided before it ran. The next few minutes decide how much of that survives.",[10,17,18],{},"Here is the part that most answers to this get wrong. They tell you to roll the\ncode back, or to ask the agent to undo it. Neither one touches your data, and\nwhile you try them the one thing you do still control is quietly getting worse:\nwhat your app is writing to the database right now.",[20,21,23],"h2",{"id":22},"what-can-i-recover-after-an-ai-agent-deletes-my-data","What can I recover after an AI agent deletes my data?",[10,25,26],{},"Whatever was in the last copy of your database taken before the delete ran, and\nnothing that was made after it.",[10,28,29,30,34,35,38],{},"That is the whole answer, and most of it was settled weeks ago. There is no\nforensic step here, nothing to undelete, no log sitting in Supabase waiting to\nbe replayed. A row removed by a ",[31,32,33],"code",{},"DELETE"," or a ",[31,36,37],{},"DROP TABLE"," is gone from the\ndatabase the moment the statement commits. What comes back is a copy, and a copy\neither exists or it does not.",[10,40,41],{},"So there are two jobs in front of you. Find out which copies exist. And stop the\ngap between the newest one and now from getting any more expensive than it\nalready is.",[20,43,45],{"id":44},"stop-your-app-writing-to-the-database-first","Stop your app writing to the database first",[10,47,48],{},"Before you go looking for a backup, turn off anything that writes new rows.\nReads are fine.",[10,50,51],{},"There are two reasons, and the second one catches people.",[10,53,54],{},"The first is that a restore is not a merge. Putting a copy back replaces the\ntables it contains with what those tables held at the time, so everything\nwritten after that copy goes with it. A customer who signs up during the hour\nyou spend reading this is a row you will delete yourself, later, in a step you\nhave already decided to take.",[10,56,57],{},"The second is that some routes get worse while you wait. Supabase's\npoint-in-time recovery rewinds the whole project to a minute you choose, which\nmeans the further the app gets from the mistake, the more genuine work that\nrewind throws out alongside the damage.",[10,59,60],{},"An hour behind a maintenance notice is a cheap thing. Telling somebody their\norder was created and then deliberately removed is not.",[20,62,64],{"id":63},"can-i-ask-the-agent-to-undo-it","Can I ask the agent to undo it?",[10,66,67],{},"No. It never held your rows.",[10,69,70],{},"The agent wrote an instruction and your database carried it out. What it has now\nis a transcript of that conversation, which is a different object from a copy of\nthe table. Ask it to reverse the delete and you get a confident answer, some\nplausible SQL, and no data.",[10,72,73],{},"The risk is worth being specific about, because the request feels harmless.\nRunning the agent again means a second unsupervised session against a live\ndatabase that has already lost something. If it decides the way to fix a missing\ntable is to create one, you now have a new empty table standing where the old\none was, and you have made the loss harder to describe to whoever helps you\nnext.",[10,75,76,77,82],{},"Take it off the project until you know where you stand. The same goes for your\nbuilder's version history: rolling your code back to this morning restores your\npages and leaves your data exactly where it is now, for\n",[78,79,81],"a",{"href":80},"\u002Fblog\u002Fversion-history-is-not-a-backup","reasons worth understanding once",".",[20,84,86],{"id":85},"where-to-look-in-order","Where to look, in order",[10,88,89],{},"Work down this list and stop at the first one that exists. It runs in order of\nhow much of your data comes back, which is not the order of how easy they are.",[91,92,93,109],"table",{},[94,95,96],"thead",{},[97,98,99,103,106],"tr",{},[100,101,102],"th",{},"Where to look",[100,104,105],{},"What it can give back",[100,107,108],{},"What had to be true already",[110,111,112,124,135,146,161,172,187],"tbody",{},[97,113,114,118,121],{},[115,116,117],"td",{},"Supabase point-in-time recovery",[115,119,120],{},"The database as it was at a minute you choose, including the one before the delete",[115,122,123],{},"A paid plan with the PITR add-on, bought before today",[97,125,126,129,132],{},[115,127,128],{},"Supabase daily backup",[115,130,131],{},"The database as it was at the last automatic copy",[115,133,134],{},"A paid plan",[97,136,137,140,143],{},[115,138,139],{},"A managed backup service",[115,141,142],{},"The database as it was at that service's last checked copy",[115,144,145],{},"You connected one before today",[97,147,148,155,158],{},[115,149,150,151,154],{},"A ",[31,152,153],{},"pg_dump"," you ran yourself",[115,156,157],{},"Everything in the file, which is as old as the last time you remembered",[115,159,160],{},"The file exists and finished writing",[97,162,163,166,169],{},[115,164,165],{},"A soft-delete or audit table in your app",[115,167,168],{},"Only the rows your app was already keeping a record of",[115,170,171],{},"You built it that way on purpose",[97,173,174,177,184],{},[115,175,176],{},"Your builder's version history",[115,178,179],{},[180,181,183],"key-verdict",{"type":182},"danger","Nothing",[115,185,186],{},"It versions your code, and your data lives in another service.",[97,188,189,192,196],{},[115,190,191],{},"Asking the agent again",[115,193,194],{},[180,195,183],{"type":182},[115,197,198],{},"It has never held a copy of your rows.",[10,200,201,202,206],{},"Every route that returns anything has the same requirement, and it is the one\nthat settles this: it had to exist before the delete ran. None of them can be\nswitched on now and made to reach backwards.\n",[78,203,205],{"href":204},"\u002Fblog\u002Fdoes-supabase-back-up-my-database","Which Supabase plan you are on settles the top two",",\nand checking takes about two minutes.",[20,208,210],{"id":209},"what-you-get-back-and-what-falls-in-the-gap","What you get back, and what falls in the gap",[10,212,213],{},"The copy, as it was, and nothing that happened after it.",[10,215,216],{},"The rows created between that copy and the delete are not damaged and they are\nnot hiding somewhere awkward. They were never written down anywhere except the\ndatabase they have been removed from. That is the hard part to accept while you\nare looking at an empty table, because losing something usually means it is\nstill somewhere.",[218,219],"diagram",{"alt":220,"caption":221,"src":222},"A left-to-right timeline. Three ticked copies sit along it, each with the rows it holds drawn above as small filled dots. After the last copy, more dots accumulate, then a red cross marks the delete. The dots between the last copy and the cross sit in a shaded band and are each crossed out.","A restore returns you to the last copy. The rows in the shaded band were never written down anywhere else, so nothing brings those back.","\u002Fblog\u002Fai-agent-deleted-my-database\u002Fthe-gap-1600x460.png",[10,224,225],{},"How wide that band is depends entirely on what was taking the copies. A nightly\nbackup can put a whole working day in it. Point-in-time recovery narrows it to a\nminute, which is most of why it costs extra. A dump you ran when you happened to\nthink of it puts however long ago that was in it.",[10,227,228],{},"There is a version of this where the gap barely matters, on an app whose data is\nmostly your own content and changes slowly. There is a version where it matters\na great deal: anything holding orders, messages or signups, where a day of rows\nis a day of people who will notice.",[20,230,232],{"id":231},"the-agent-deleted-some-of-it-not-all-of-it","The agent deleted some of it, not all of it",[10,234,235],{},"Then you have a real choice to make, and neither answer is clean.",[10,237,238],{},"A restore does not put the missing rows back and leave the rest alone. It\nreplaces the tables in the copy with what those tables held at the time,\nwholesale. Restoring gets back what the agent removed and reverts every good row\nwritten since. Not restoring keeps the good rows and leaves the hole.",[10,240,241],{},"Which one is right depends on how much genuine work sits after the copy. If the\nanswer is almost none, restore and move on with your day. If the answer is three\ndays of customer records, the slower route usually wins: export the surviving\nrows first, restore, then put the exported rows back on top. It is fiddly, and\nit is the only path that loses nothing.",[10,243,244],{},"It is also the argument for copying the database in its current broken state\nbefore you touch anything at all. Whichever way you decide, you want to be able\nto get back to the state you started from.",[218,246],{"alt":247,"caption":248,"src":249},"Three database shapes in a row. The first is the current state, crossed, with an arrow leading up into a copy of it that is ticked and set aside. The second is the chosen restore point being replayed in. A return arrow runs from the copy set aside back to the result, showing the restore can itself be reversed.","Copy the broken state before you replace it. It is the difference between a decision you can change your mind about and one you cannot.","\u002Fblog\u002Fai-agent-deleted-my-database\u002Fsafety-copy-first-1600x520.png",[20,251,253],{"id":252},"how-the-same-hour-goes-when-a-copy-already-exists","How the same hour goes when a copy already exists",[10,255,256],{},"Shorter, and mostly a decision rather than a search. You pick a copy, you check\nwhat it held, and you press the button.",[10,258,259],{},"That is what Reeve Care does: checked copies of your Supabase database on a\nschedule, encrypted and kept outside your Supabase account, with a one-click\nrestore behind them. Before a restore runs it takes a fresh copy of the current\nstate, so the restore itself can be undone.",[10,261,262],{},"The limits belong in the same breath, because knowing them is how you decide\nwhether it fits:",[264,265,266,270,273,276,279],"ul",{},[267,268,269],"li",{},"It copies your database, and the files your users uploaded once you connect your Storage buckets. Connecting those is optional and takes a second key.",[267,271,272],{},"It works with Supabase and nothing else today.",[267,274,275],{},"You restore to a copy that exists, not to any minute you name. Worst case you lose one interval, which is up to a night on the entry plan and shorter on the two above it.",[267,277,278],{},"Login accounts are never touched. Nobody is signed out, deleted, or brought back.",[267,280,281],{},"The database key it stores can only read, which was the promise when you connected it. Writing data back needs one that can write, so a restore asks for your database password each time and keeps none of it. The optional key for your files can write, because Supabase issues no read-only key for Storage, and the page where you hand it over says so before you do.",[10,283,284,288,289,291,292,296],{},[78,285,287],{"href":286},"\u002F#pricing","What each plan covers"," is on the homepage. If you would rather not\npay for any of it, the plain version of the same protection is a ",[31,290,153],{}," on a\nschedule you genuinely keep, held somewhere that losing your Supabase account\nwould not also take.\n",[78,293,295],{"href":294},"\u002Fblog\u002Fthree-ways-to-back-up-a-supabase-database","The three routes and what each one misses","\ncovers that without a sales pitch.",[10,298,299,300,82],{},"You can see that hour drawn out, copy by copy, on the ",[78,301,303],{"href":302},"\u002Fsupabase-backups","Supabase backups\npage",[20,305,307],{"id":306},"what-to-do-right-now","What to do right now",[309,310,311],"key-takeaways",{},[264,312,313,316,319,322,325],{},[267,314,315],{},"Stop anything that writes to the database. It is the only step here that gets more expensive the longer you leave it.",[267,317,318],{},"Establish which copies exist before deciding anything: your Supabase plan first, then any dump you took yourself, then whether your app keeps a record of deleted rows.",[267,320,321],{},"Copy the database as it is now, broken and all. Whatever you do next, you want a way back to this.",[267,323,324],{},"After a restore, check the app can still write. A database that reads correctly and refuses an insert is a half-finished restore, and only an insert proves it.",[267,326,327],{},"Once the immediate thing is over, set up the copy that would have made this a ten-minute problem instead of a morning.",[10,329,330,331,335],{},"Before you close this tab, open your Supabase project and find out whether\nanything at all is copying your database, then write down where that copy lives.\nThe ",[78,332,334],{"href":333},"\u002Fchecklist","10-minute security checklist"," covers it alongside the other\nthings worth confirming on a newly launched app.",{"title":337,"searchDepth":338,"depth":338,"links":339},"",3,[340,342,343,344,345,346,347,348],{"id":22,"depth":341,"text":23},2,{"id":44,"depth":341,"text":45},{"id":63,"depth":341,"text":64},{"id":85,"depth":341,"text":86},{"id":209,"depth":341,"text":210},{"id":231,"depth":341,"text":232},{"id":252,"depth":341,"text":253},{"id":306,"depth":341,"text":307},"Backups",null,"An AI agent deleted your database data. What you can recover was decided before it ran, and the next few minutes decide how much of it survives.",false,"md",[355,358,361,364,367],{"q":356,"a":357},"An AI agent deleted rows in my Supabase database. Can I get them back?","Only from a copy taken before it ran, so the first thing to establish is whether one exists. Check what your Supabase plan includes, then check for any dump you took yourself, then check whether your app happens to keep a record of deleted rows. If none of those exist, the rows are gone, and no amount of work on the app will change that. Establish this before you write anything new to the database.",{"q":359,"a":360},"Can I ask the agent to put the data back?","No. The agent never held your rows. It sent an instruction to your database and the database carried it out, so what it has now is a transcript of the conversation rather than a copy of the table. Asking it to reverse the delete gets you a confident answer and no data. It also means a second unsupervised session against a database that has already lost something.",{"q":362,"a":363},"I am on the Supabase free plan. Is there anything to recover?","Not from Supabase. Automatic backups start on the paid plans and point-in-time recovery is an add-on above that, so a free project has no copy of yesterday sitting anywhere. What is left is a dump you took yourself, or a soft-delete or audit table your app was already writing. Check both before you assume the worst, and check them before you keep using the app.",{"q":365,"a":366},"Should I keep the app running while I work out what to do?","Turn off anything that writes. Reads are fine. New rows are a problem twice over: restoring a copy removes everything added after it, so an order that arrives now is data you will delete yourself later, and a point-in-time rewind has more real work to throw away the longer you leave it. A maintenance notice for an hour costs less than the second loss does.",{"q":368,"a":369},"The agent deleted some rows but not all of them. Do I still restore everything?","That is the awkward case and there is no clean answer. A restore replaces the tables in the copy wholesale, so it brings back what you lost and also reverts every good row written since. Which way to go depends on how much real work sits after the copy. If it is a lot, exporting the surviving rows first and putting them back on top of the restore is slower and loses nothing.","\u002Fblog\u002Fai-agent-deleted-my-database\u002Fcard-800x500.png",[372,373,374,375,376],"ai deleted my database data recover","ai agent deleted my data","cursor deleted my database","ai agent dropped a table","recover data after ai delete",{},true,"An AI agent deleted my Supabase data","\u002Fblog\u002Fai-agent-deleted-my-database","2026-08-21",{"title":5,"description":351},"blog\u002Fai-agent-deleted-my-database",[385,386,387],"If an AI agent deleted your database data, what you can recover is whatever was in the last copy taken before it ran. Nothing made after that copy was ever written down anywhere else.","Stop your app writing new rows before you do anything else. A restore removes everything added after the copy, so a signup that arrives now is a row you will delete yourself.","The agent cannot put the rows back. It never held them, and running it again against a live database is another chance to lose more.","3HN4Ydx1z6k6BHmO-QO6dpzDsf_F0qzhZJxSZoHr_uI",1787826048204]