If you accidentally deleted a production database, stop application writes before you attempt a restore. Preserve the deletion time, database and platform logs, deployment history, and current state. Then restore to a separate destination when the provider supports it, validate the copy, and decide how to handle writes that occurred after the recovery point.
Do not run a migration, recreate tables by hand, or point production at the first backup you find. Those actions can overwrite surviving evidence and make reconciliation harder.
The first-hour database recovery runbook
The safest order is containment, evidence, recovery-point selection, validation, and controlled return to service.
- 01 Stop new writes. Put the app in maintenance or read-only mode, pause workers and scheduled jobs, and disable webhooks that mutate data. If the destructive process is still running, stop it.
- 02 Revoke the path that caused the deletion. If an exposed secret, agent, or automated job was involved, rotate that credential, terminate affected sessions where the platform allows it, and remove the job from the environment. Do not destroy its logs.
- 03 Record an incident time in UTC. Save the first alert, the last known good transaction, the destructive command or platform event, deployment identifiers, and audit logs before retention windows or redeploys remove them.
- 04 Confirm the scope. Check whether the database, one schema, selected tables, storage objects, authentication records, or backups were affected. Treat each data store as a separate recovery surface.
- 05 List available recovery points. Check point-in-time recovery, snapshots, logical dumps, replicas, exports, event streams, billing records, and staging copies. Record the timestamp and documented limits of each one.
- 06 Restore into a separate database or service when possible. Keep the damaged source untouched until the restored copy has passed integrity and application checks.
- 07 Validate before cutover. Check schema versions, row counts, constraints, a sample of critical records, authentication, storage references, and one complete business workflow. Reconcile later writes before reopening traffic.
Assign one person to approve recovery actions and another to record them. A shared incident log prevents two well-intentioned people from restoring different snapshots or changing credentials without telling each other.
Am I going to be fired?
No page can promise you an outcome, but the structural reading is in your favour. If one command could reach production data with no approval step and no tested backup between it and the business, the system failed before you touched it. Any honest review lands on the missing control, not the keystroke. That does not make it comfortable. What reliably makes it worse is hiding it.
Say it out loud to one person in the first few minutes. A quiet fix attempt is what turns a recoverable incident into an unrecoverable one, because the repair steps overwrite the evidence and the recovery points you still needed. Write down what you ran, against which host, and at what time in UTC, before your memory of it softens.
Tell people in this order: whoever can authorize downtime (co-founder, manager, or the on-call owner) first, then the client or account owner if the app is not yours, then customers once you know the scope. The first two conversations are short and factual: what is down, what is stopped, what you are checking, when you will report again. Customers can wait thirty minutes for a scoped statement, and they will forgive that far more easily than a correction to a wrong one.
Do not commit to anything in writing before you know the scope. No “everything is recoverable”, no “no customer data was affected”, no restore time, no fault assignment. Give a next-update time instead and keep it. Those four sentences are the ones that get quoted back at you in a contract dispute.
If an AI agent deleted it
An agent deleting the database changes the first moves, because the thing that did it is still running and still holds a credential.
- 01 Stop the run before anything else. Closing the browser tab or the terminal window does not always stop a run that executes server-side, and a stopped run is the only version of this incident that has an end.
- 02 Revoke the credential, not the session. The API token, database URL, or service key you handed the agent is what did the work. Rotate it at the provider and check whether the same value is pasted into other tools, MCP servers, or a .env file that a teammate is running right now.
- 03 Export the run log immediately. Chat transcripts, agent run logs, and tool-call histories get truncated, rotated, or lost on a new session in most tools. Save the raw text now: it is your only record of what commands the agent ran and in what order.
- 04 Map what else that credential could reach. An overscoped token that could delete the database could usually also delete storage buckets, backups, other environments, or the project itself. Check each one before you assume the damage stops at the database.
This applies whether the agent was Claude Code or Cursor running on your machine with your local credentials, or Lovable, Base44, Bolt, v0, or a Replit agent running in the vendor’s environment against a database you connected to it. The tool differs, the credential does not. Every one of these fails the same way when the key you gave it can reach production, and no instruction in a prompt, a rules file, or a system message is a permission boundary. The provider honors an authenticated call regardless of what the agent was told.
If a Replit, Lovable or Base44 agent did it
The credential is the same problem in every tool. Where the data lives, and therefore where you go to get it back, is not. If a Replit, Lovable or Base44 agent deleted the production database, those are three different recoveries.
Replit. Establish which of the two databases actually went before you restore anything. Replit’s development and production database documentation says Agent can modify the development database and cannot modify the production one, so a Replit production database deleted during an agent session usually went through something else in the same session: a connection string sitting in the code, a migration the agent wrote and you ran, or a script holding production credentials. Replit documents the two restore paths separately, so picking the wrong one restores the wrong database. Check the connection string the failing command used rather than the agent’s own account of what it touched.
Lovable. Its Supabase integration connects a Supabase project you own and runs it as the app’s backend, so if that is how the app was set up, the recovery surface is Supabase’s and the Supabase row in the platform table further down is the one that governs you. Open the Supabase dashboard yourself. Asking the builder to fix it puts a second writer on a damaged database while you are still working out what is missing.
Base44. The database is Base44’s own, so no provider dashboard of yours will show it and no pg_dump of yours exists. Export every table that still has rows in it to CSV from the Data dashboard as its data documentation describes, before you try any recovery step. An export taken ten minutes after the incident is a recovery point, and it is the only one that does not depend on your plan.
The commands that cause this
Almost every incident of this shape traces back to one of a short list of commands, run against the wrong target.
DROP DATABASE app_production;
DROP TABLE users;
TRUNCATE orders;
DELETE FROM orders; -- no WHERE clause
supabase db reset --linked # drops the user-created entities in the LINKED remote project
npx prisma migrate reset # drops the database, reapplies migrations, reseeds
npx prisma db push --force-reset # resets before pushing the schema
npx drizzle-kit push # destructive when you accept the data-loss prompt
mongosh "$MONGO_URL" --eval 'db.dropDatabase()'
Where your platform offers point-in-time recovery, it can walk back past every command in both blocks, provided the log window still covers the minute before it ran. Each one is an ordinary transaction the database wrote down, so PITR can rebuild the state that existed a second earlier. What PITR cannot walk back past is the deletion of the project, instance, or volume holding those logs, because the log is inside the thing that went away.
Most of these commands are safe in the place they were designed for. They become a production delete when there is one combined database for development and production, because the reset you meant for your throwaway test rows is pointed at the only database you have. A combined database also removes the pause where you would have noticed the target, since there is no separate connection string, no second project, and no moment where the environment name looks wrong. That is the setup described in one database, no staging, deploy set to break.
What can a backup recover?
Recovery depends on the newest usable recovery point, not the label on the backup screen. Point-in-time recovery can usually rebuild a database to a timestamp inside its retained log window. It does not guarantee zero data loss: missing or delayed transaction logs, an expired retention window, excluded services, or corruption can move the latest usable point backward.
| Evidence available | Recovery expectation |
|---|---|
| Verified point-in-time recovery with an intact log window | Restore to a chosen time before the destructive operation. Transactions after that time need separate reconciliation. |
| A verified snapshot or logical dump | Recover the state captured by that backup. Writes after its timestamp are absent unless another source recorded them. |
| A replica | Potentially useful only if replication was stopped before the destructive change reached it. A live replica can copy the deletion too. |
| Logs, webhooks, exports, emails, or payment records | Partial reconstruction. These sources may prove that an action happened without containing every field needed to rebuild it. |
| No usable recovery point or secondary record | Escalate to the provider and preserve the original storage. Do not promise recovery until the provider confirms what remains. |
A backup is usable after a restore test proves that the database starts, the application can read it, and critical relationships are intact. Across the apps AxonBuild audited in June and July 2026, the recurring data-safety finding was a backup switched on and never once restored, so the honest default is to assume yours restores slower and covers less than the dashboard implies until a drill proves otherwise. The Supabase backup and restore guide covers those checks for Supabase projects.
What each platform actually gives you
What you can restore is decided by your provider and your plan, and the free-tier answer is usually thinner than founders expect. These are the documented defaults as of 5 August 2026:
| Platform | Backups you get by default | Point-in-time recovery |
|---|---|---|
| Supabase | Free plan: none automated. The docs tell you to export with the CLI yourself. Pro keeps 7 days of daily backups, Team 14 days, Enterprise up to 30. | Paid add-on on Pro, Team, and Enterprise, with a 7, 14, or 28 day retention period. Enabling it replaces daily backups. |
| Railway | Volume backup schedules you choose: daily kept 6 days, weekly kept 1 month, monthly kept 3 months. | Yes for Postgres. Railway keeps the last 4 full backups, roughly a 4 week window, and the window starts at the first backup after you enable it, not retroactively. |
| Neon | The history window is the restore surface. Default 6 hours on Free, 1 day on Launch and Scale. | Instant restore inside that window. Maximum 6 hours on Free, 7 days on Launch, 30 days on Scale. |
| Vercel Postgres | Retired. Existing databases were moved to Neon in December 2024, so Neon’s rules apply. | See Neon. |
| Firebase Firestore | Daily and weekly backup schedules you configure, retained up to 14 weeks. | 7 days at minute granularity once PITR is enabled. Without it you can read back about 1 hour. |
| PlanetScale Postgres | Automatic backups every 12 hours on production and development branches at no extra charge, kept 2 days. | Yes, to any timestamp between the oldest backup and 5 minutes ago. |
Two things follow from that table. First, check your own dashboard against the row for your platform now, not during an incident, because tiers and retention windows move. Second, notice how many of these windows are measured in hours or days: a delete you discover on Monday morning may already sit outside the free-tier window it happened in.
You deleted the project, not just the data
Deleting the whole project, instance, or volume is a different incident from deleting rows or tables, and a worse one. The backups usually live inside the boundary you deleted, so they go with it. Provider PITR logs, automated daily backups, and snapshots attached to that project are all inside the thing that no longer exists.
Some providers say this outright. Supabase’s own delete-project page states that it cannot recover deleted projects and that all data, backups, and configurations are permanently removed (Supabase, Deleting Your Project). Others hold a short soft-delete or grace window, and the only way to know which one you are in is to ask them, fast.
Open a support ticket in the first ten minutes. Include the exact project ID or reference, the region, the deletion timestamp in UTC, the account or token that performed the deletion, and a plain statement that this was production data. Ask one specific question: does any recoverable copy of this project’s storage still exist, and until when. That is a different question from “can you help”, and it gets a different answer.
While you wait, do not recreate a project with the same name and start writing to it, and do not delete anything else in that account. Then hunt for copies outside the deletion boundary: a pg_dump file on someone’s laptop, a staging or preview database, CI seed data, an analytics warehouse or BI extract, a spreadsheet export a teammate made, and records held by your payment processor or email provider. Reconstruction from those sources is partial, but it is often the difference between a bad week and a closed business.
Should you restore into a copy or over production?
A separate restore gives you three things: the damaged source remains available for investigation, validation can happen without live writes, and rollback remains possible if the selected recovery point is wrong.
Provider behavior differs. Railway’s current point-in-time recovery process provisions a new Postgres service and leaves the source untouched. Its volume-backup restore mounts a newly restored volume, retains the previous volume unmounted, and removes backups newer than the selected restore point. Read the exact restore behavior for your provider before clicking anything: Railway documents PITR separately from volume backups, and its volume backup page lists the restore sequence and caveats.
If the provider only offers an in-place restore, take a snapshot or export of the current damaged state first if support confirms that doing so is safe. Record who approved the in-place operation and what it will overwrite.
Validate the recovered database
A green restore status shows that the restore job finished. It does not show that the recovered application works.
Check these surfaces before cutover:
- The schema version matches the application version you will deploy.
- Critical tables exist, constraints validate, and recent row counts are plausible.
- Authentication records and authorization policies still match the recovered schema.
- Database rows that reference files, queues, search indexes, or third-party objects still point to valid objects.
- One representative workflow completes from the user interface through the database and back.
- Background workers are paused until you know they will not replay stale jobs or duplicate side effects.
Choose an explicit reconciliation window: from the restored timestamp to the moment writes stopped. Payment processors, email providers, signed webhook archives, and append-only event logs may help rebuild part of that interval. Make every replay idempotent so the reconciliation job cannot charge, email, or fulfill twice.
Preserve evidence and notify the right people
An accidental delete can also be a security or privacy incident. Preserve access logs and ask who or what used the credential, whether the credential was exposed, and what else it could reach. Rotate related credentials based on scope instead of stopping at the one visible token.
Tell affected customers and regulators when contracts or applicable law require it. The notification decision depends on the data involved, the jurisdictions, the outage, and whether confidentiality or integrity was affected. Record the decision and get legal or privacy advice where the obligation is uncertain.
What the PocketOS incident demonstrates
In April 2026, PocketOS founder Jer Crane reported that a Cursor agent working on a staging task used an over-scoped Railway API token to delete a production volume and its volume-level backups. The token had been created for domain management but could run any operation Railway’s API allows, deleting a volume included. Crane posted the agent’s own self-assessment afterward, and it lands on the exact gap: “I guessed that deleting a staging volume via the API would be scoped to staging only. I didn’t verify.” Railway’s CEO put the deeper problem on the record: the platform honors any authenticated delete call, agent or human, with nothing in between to ask whether the caller should have been allowed to make it. Reporting at the time said Railway later recovered the data and changed API deletion behavior.
The useful lesson is the permission boundary. A staging task could reach a production resource, and the destructive API path had more immediate effect than the dashboard path. A written instruction against destructive commands cannot replace separate projects, narrowly scoped credentials, protected production actions, and recoverable backups. The same boundary problem appears in single-database deployments without a staging environment.
The Replit case nine months earlier was the same failure with different names. In July 2025, Replit’s coding agent deleted the production database behind an app SaaStr founder Jason Lemkin was building in public. Replit’s own account says rollback fully restored the data, but Agent did not know rollback existed and was not helpful during the recovery. The incident predated Replit’s separate development and production databases, which the company later shipped. Read it through the same lens as PocketOS: the agent held a live connection to production, and nothing sat between that connection and the delete to ask whether this particular run should be allowed to make it.
What comes back in the next hour was decided months before the incident, not during it.
An AxonBuild audit found the same shape with no AI agent anywhere near it: a leftover maintenance endpoint that could drop the entire production database in a single request, guarded by nothing but a secret in the query string. An overscoped credential and an unprotected endpoint fail the same way: one path reaches everything, and nobody built a wall partway down it. The same shape decides whether Supabase is safe on a given project, where a service_role key in client code skips every policy behind it.
Why the PocketOS story gets searched under Claude’s name
Coverage of the PocketOS deletion attached the model’s name to the incident, rather than naming only the tool around it. One outlet’s headline read “Claude-powered AI coding agent deletes production database and backups in 9 seconds”; another led with “Cursor tool powered by Anthropic’s Claude goes rogue” once it came out the agent ran on Claude Opus 4.6. Coverage of the Replit incident nine months earlier usually named Replit, which built and operated that agent under its own brand.
PocketOS’s agent ran on a model Anthropic trained. It sat inside a tool Cursor built. It reached a database Railway hosted. Swap any one of those three next quarter, and an overscoped token pointed at an undivided database still fails the same way.
How do you stop it happening again?
Write down the recovery point objective and recovery time objective you actually achieved. Then install mechanisms, not intentions. Each of these is something a person can go build this week:
- A Postgres event trigger that blocks DROP for the application role. A
ddl_command_starttrigger that raises an exception on drop statements makes the destructive command fail even when the connection string is right. It guards objects inside the database, not the deletion of the database itself. - A read-only role as the default human login. Humans connect read-only by default and switch to a write role deliberately for the minutes they need it. Most “I ran it against prod” incidents are a read-shaped task on a write-capable connection.
- The provider’s deletion-protection flag, set on the project, database, instance, and volume. It costs nothing and it turns a one-click delete into a two-step one.
- One API token per environment, scoped to one project. No token that can reach both staging and production, and no reuse of a token created for another purpose. This is the exact control both the PocketOS and Replit incidents were missing.
- An environment name on screen before you type. A shell prompt, a
psqlconnection alias, or aPROMPT1that prints PRODUCTION in red. Identical command syntax across environments is what makes the wrong host invisible. - A
pg_dumpcopy stored outside the provider account, on a schedule, so the backup does not live inside the boundary that can be deleted. Alert when the dump job or WAL archiving stops, because silent backup failure is the normal failure mode. - A timed restore drill on the calendar, including reconciliation of the transactions that fall between a recovery point and containment. The drill is what converts a backup into a recovery time you can quote.
The post-incident review should name the failed control and its owner. A blameless postmortem is not a soft one: it moves the finding from the person to the missing boundary, and then someone has to own building it. “Be more careful” does not create a boundary the next command has to cross.
Common questions about a deleted production database
Can I recover a deleted production database?
You can recover it when a usable backup, point-in-time recovery window, snapshot, or secondary record still exists. Restore to a separate destination where possible and validate it before cutover. Without a usable recovery point, only the provider can determine whether deleted underlying storage remains recoverable.
Should I restore the latest backup immediately?
Usually, no. Stop writes, preserve evidence, verify the backup timestamp and scope, and restore into a copy first. The latest backup may already contain the destructive change, may exclude related data, or may be older than another available recovery point.
How long will a database restore take?
There is no safe universal estimate. Database size, backup type, transaction-log volume, provider behavior, and validation work all affect recovery time. PocketOS’s data came back in about an hour once Railway’s CEO stepped in directly, two days after the delete. That is a best case with a vendor engineer working the problem in person, not the default timeline for a routine restore request. A timed restore drill is the only reliable estimate for your system.
Does a read replica count as a backup?
No. Replication commonly carries destructive writes to the replica. A replica helps only if it was isolated before the deletion reached it or if it supports a retained historical recovery mechanism.
Will I be fired for deleting the production database?
No page can promise that, but the structural reading is in your favour: if a single command could reach production with no approval step and no tested backup in the way, an honest review lands on the missing control rather than on the keystroke. Tell one person immediately, write down exactly what you ran and when, and do not attempt a quiet fix, because quiet fixes destroy the evidence and the recovery points you still need.
Does deleting the database delete the backups too?
It depends on where the backups live. Provider-managed backups, snapshots, and point-in-time recovery logs usually sit inside the project or instance you deleted, so deleting the project takes them with it. A copy stored outside that boundary, such as a pg_dump in your own storage or a warehouse export, survives, which is the reason to keep one.
Can a deleted Supabase or Railway project be restored?
Supabase says no: its documentation states that it cannot recover deleted projects and that all data, backups, and configurations are permanently removed. Other providers differ and some hold a short internal window, so open a support ticket immediately with the project ID, the region, and the deletion timestamp in UTC. Do not recreate a project with the same name while you wait for their answer.
What should I do if an AI agent deleted my database?
Stop the agent run first, then revoke the API token or key it used instead of just closing the window, because closing a tab does not stop a run that executes server-side. Export the chat or run log straight away, since most tools truncate or rotate it. Then check every other resource that credential could reach, because an overscoped token rarely opens only the one thing that broke.
What do I do if the agent also deleted the backups?
Work the credential, not the database. A token that could reach the backups could usually also reach snapshots, other environments, storage buckets, and the project itself, so list what else is gone before you try to recover anything, then open a provider support ticket in the first ten minutes with the project reference, the region, and the deletion time in UTC. Ask one specific question: does any recoverable copy of this storage still exist, and until when.
While you wait, search outside the boundary the agent could reach rather than inside it. A pg_dump on a laptop, a preview or staging copy, CI seed data, a warehouse or analytics extract, a spreadsheet a teammate downloaded, and the records your payment and email providers hold are the places to check; before you rely on any of them, confirm it still exists and that the affected credentials could never reach it, because an overscoped token that reached the backups may have reached a staging copy too. Keep the agent’s run log while you do it, because it is the only ordered account of which recovery points existed at the moment it ran and which ones it removed.
How do I recover a deleted Supabase project’s data?
If the project itself was deleted, your recovery depends on copies made outside it: CLI dumps, staging or preview databases, warehouse extracts, and records held by your payment or email providers. If the project still exists and only data was deleted, use daily backups (Pro and above) or the point-in-time recovery add-on if it was enabled, and restore into a new project before touching the damaged one.
Built it with AI. Can’t get the last part right?
That’s the normal state of an AI-built app, and it’s fixable. I trace what the app actually does, explain what needs changing, and build it if you want me to.
Talk about your app →
Free 20-minute video call with me.