Stop every write and every agent first. A deleted database in production is restored from the newest backup or point-in-time recovery point taken before the deletion, and anything still running can recreate empty tables, replay jobs or delete more. Then record the time in UTC, check what your provider kept, and restore into a separate copy.

Deleted database: what to do in the first hour

A deleted database in production is recovered in a fixed order: stop writes and any agent, record the time in UTC, confirm what was deleted, list every recovery point with its timestamp, restore into a separate copy, and check that copy before traffic returns. Skipping ahead can overwrite the evidence and the recovery points you still need.

The order holds whether the deleted production database went with a command typed into the wrong terminal, a migration or an agent’s API call; what changes is who still holds the credential. Write this restore runbook down before the next incident, using the runbook template for a small SaaS, so the next person to face it reads steps instead of guessing.

  1. 01 Stop new writes. Put the app in maintenance or read-only mode, pause workers, scheduled jobs and webhooks that change data, and stop the process that did the deleting if it still runs. Record what you paused and at what time.
  2. 02 Revoke the path that caused it. Rotate the credential that ran the command, end the job or the agent run, and keep its logs. Record which credential it was and every place it is stored.
  3. 03 Record an incident time in UTC. Save the last good transaction, the command or platform event, deploy ids and audit logs before retention or a redeploy removes them.
  4. 04 Confirm the scope. Check whether a whole database went, or one schema, some tables, storage objects, auth records, or the backups too. Write each store down as its own line.
  5. 05 List every recovery point. Point-in-time recovery, snapshots, dumps, replicas, exports and staging copies each get a line with the timestamp and the limit its docs give.
  6. 06 Restore into a separate database when the provider allows it, and leave the damaged source untouched. Record the recovery point you chose and the reason.
  7. 07 Check the copy and reconcile later writes before traffic returns. Record each check and who signed it off.

Split the work between two people if you can: one approves each recovery action, the other writes it down as it happens. That is our working rule for any restore, because the written log is what the review reads afterward. Until the copy passes its checks, do not run a migration, rebuild missing tables yourself or point production at the first backup you find.

If an AI agent deleted it

An agent changes the first moves, because the thing that did the deleting is still running and still holds a credential.

  1. 01 Stop the run. Closing a browser tab or a terminal window may not stop a run that executes on the vendor's servers.
  2. 02 Revoke the token, database URL or service key the agent used, at the provider. Then look for the same value in other tools, MCP servers and .env files.
  3. 03 Export the run log or the chat now. Tools truncate or rotate them, and the log is the only ordered record of what the agent ran.
  4. 04 List everything else the credential could reach: storage buckets, backups, other environments and the project itself.

When an AI agent deleted the database, what it was told matters less than what its key allowed: a prompt, a rules file or a system message is not a permission boundary, and the provider honors an authenticated call whatever the agent was instructed.

Where the data lives decides where you recover it. Replit’s development and production databases page says “Agent is not able to modify the production database”, so if an agent session seemed to delete the production database on Replit, check what else ran in it, such as a connection string in the code or a migration you ran yourself. Lovable’s Supabase integration “connects a Supabase project you own” as the app’s backend, so an app set up that way recovers in your own Supabase dashboard. Lovable’s built-in Cloud backend is the default, and the same page lists “daily backups with restore” from inside Lovable among its managed features, so look for the newest restore point there and ask Lovable’s support what else exists. A Base44 app keeps its data in Base44’s own database, so export every table that still has rows before any recovery step; Base44’s data export hands it over as a CSV file. The rules that keep an agent away from production in the first place are guardrails for AI coding agents.

Who to tell first, and what not to promise

Say it out loud to one person in the first minutes. A quiet fix attempt is how a recoverable incident becomes an unrecoverable one, because repair steps overwrite the evidence and the recovery points you still need.

Tell people in this order: whoever can approve downtime, then the client or account owner if the app is not yours, then customers once you know the scope, with a short notice on a status page for a small SaaS. Put nothing in writing yet that promises full recovery, no customer impact, a restore time or a cause. Give a next-update time instead, and keep it.

A deletion can also be a security or privacy incident. Whether you must notify customers or a regulator depends on the data, your contracts and the jurisdiction; this is not legal advice, so get legal or privacy advice where the duty is unclear. As for blame, we think an honest review names the missing control, not the keystroke.

Why production databases get deleted

Production databases are usually deleted by an ordinary command run against the wrong target: a reset meant for a local database, a migration run on the only database there is, an agent holding a token that reaches production, or a route left open for maintenance. The command works as designed; the missing piece is a boundary.

CauseWhat it looks likeThe boundary that was missing
A reset or schema push meant for a local or staging database, run against productionA CLI reset or a forced push runs with the production connection string loadedSeparate projects per environment, and the environment name on screen
A migration on the only database there isThe migration drops or rewrites a table that customers are usingA staging database that takes every migration first
An agent or job holding a token that reaches productionA task meant for staging deletes a production resourceOne scoped token per environment
A route or script left open for maintenanceOne request to an unguarded endpoint drops tablesAuthentication and a role check on every privileged route

The second row is the setup described in one database with no staging, and the recovery for a migration gone wrong is undoing a migration that dropped tables.

In our June and July 2026 audits of 21 third-party apps, one multi-tenant point-of-sale app kept a public GET maintenance route that drops every tenant’s tables, guarded only by a secret in the query string, which ends up in logs and browser history. Those 21 apps were picked for review rather than sampled, so this is one app’s finding, not a rate for AI-built apps. The full case is in the API security checklist for AI-built apps. Where deletion safety sits among the other database checks of a product is the data consistency checklist for SaaS.

The commands that delete prod

A team can delete prod with a command that works exactly as its docs describe, pointed at the wrong database. These are the tool commands that do it, with what each one’s documentation says it does:

supabase db reset --linked          # drops all user-created entities in the linked remote database
npx prisma migrate reset            # drops the database or schema if possible, recreates it, applies all migrations
npx prisma db push --force-reset    # resets the database, then updates the schema
npx drizzle-kit push --force        # auto-accepts all data-loss statements

The sources are the supabase db reset reference, Prisma’s CLI reference, which marks migrate reset “For use in development environments only”, and the drizzle-kit push page. Each command is safe in the place it was built for. It becomes a production delete when development and production share one database or one connection string, because the reset meant for test rows lands on the only data you have. The SQL statements that delete a database are in the questions at the end of this page.

Point-in-time recovery can walk back past any of these commands while its log window still covers the minute before it ran, but not past the deletion of the project or volume that holds those logs. That is our reading of how PITR works. Railway’s page states the window half of it: its recovery restores “to any timestamp within the archive retention window”, and under sustained S3 outages that window truncates.

The Claude deleted database story: what PocketOS shows about tokens

Coverage in late April 2026 reported the PocketOS founder’s account: a Cursor agent running Anthropic’s Claude Opus 4.6 hit a credential mismatch on a routine staging task and deleted a Railway database volume through a single API call, which “deleted our production database and all volume-level backups”. Railway’s own blog post of 29 April 2026, which does not name the customer, says the agent “found a Railway API token stored locally on the user’s machine and used it to call volumeDelete on a production volume”, that the token had “account scoped access, the maximum access possible”, and that the legacy API path “performed a cascading delete on the model, making the backups look unavailable in the UI.” The same post says: “We’ve since recovered the database, and the customer is back up with all their data.” Railway’s changelog of 1 May 2026 adds that until then, volumeDelete “removed volumes immediately, with no recovery path”, and that API volume deletions now soft-delete for 48 hours.

The PocketOS story spread as a case where Claude deleted the database, because the coverage named the model, Anthropic’s Claude, while the tool was Cursor and the host was Railway. In our view, when Claude deletes a production database through a token like that one, the boundary that failed is the token’s scope, and no instruction in a prompt replaces one token per environment.

How to get it back: what a restore can recover

A restore brings back the newest usable recovery point taken before the deletion, never anything written after it. Point-in-time recovery can rebuild the state from just before the command while its log window still covers that moment; a daily backup returns the state at backup time; deleting the whole project usually deletes both.

If the database still exists and only some rows are gone, the job is smaller: getting a few deleted rows back in Postgres.

A backup counts only once a restore has proved it. GitLab deleted production database data by accident in 2017 and then learned its pg_dump backups had been failing without anyone noticing, which makes it the standard case of a backup nobody had tested by restoring it.

What each platform keeps, and for how long

PlatformBackups by defaultPoint-in-time recovery
SupabaseDaily backups on Pro (last 7 days), Team (14) and Enterprise (up to 30); free tier projects are told to export their data with the CLIPaid add-on on Pro, Team and Enterprise with 7, 14 or 28 days of retention; once it is on, daily backups stop
RailwayVolume backup schedules you choose: daily kept 6 days, weekly kept 27 days, monthly kept 89 daysPostgres: the last 4 full backups, a window of roughly 4 weeks that starts at the first base backup after you enable it
NeonThe history window is the restore range: 6 hours on Free, 1 day by default on Launch and ScaleRestore inside the window; maximum 6 hours on Free, 7 days on Launch, 30 days on Scale
Vercel PostgresNo longer available; existing databases were moved to Neon in December 2024Neon’s rules apply
Firebase FirestoreUp to one daily and one weekly schedule you configure, retained up to 14 weeks7 days at minute granularity once enabled; without it, documents can be read (not exported) within the past hour
PlanetScale PostgresEvery 12 hours on production and development branches, kept 2 days, at no extra chargeTo any timestamp between the oldest backup and 5 minutes ago
ReplitDevelopment database: checkpoint rollback with up to 7 days of historyProduction database: every plan starts at 7 days, changeable in settings up to 7 on Core and 28 on Pro and Enterprise; separate from code rollback

Checked on 20 October 2026 against Supabase’s backups docs, Railway’s point-in-time recovery, Neon’s history window, Firestore backups, PlanetScale’s Postgres backups and Replit’s data recovery, plus Railway’s volume backups, Firestore’s PITR and Vercel’s Postgres pages.

Check your own dashboard against your row now, before you need it. Many of these windows are measured in hours or days, so a deletion found on Monday morning may already sit outside a free tier’s window. Backups on any host, and the retention to set, are covered in the database backup checklist for startups; Supabase plans in detail are in Supabase backups and PITR by plan.

When the whole project was deleted

Deleting the project, instance or volume usually deletes the backups inside it. Supabase’s delete-project page says that “all artifacts are permanently removed and you cannot recover them”, a list that includes the database and the automated backups, and that “We cannot recover deleted projects.” Other hosts differ: Neon’s docs say deleted projects “can be recovered within the deletion recovery period (7 days) via the API or CLI”, and Railway’s changelog says volume deletions now soft-delete for 48 hours.

Open a support ticket straight away with the project id, the region, the deletion time in UTC and the account or token that did it. Ask one question: does any recoverable copy of this project’s storage still exist, and until when. In the PocketOS case, Railway wrote that the backups looked unavailable in its interface, and that it still recovered the database. While you wait, do not recreate a project with the same name and do not delete anything else in the account.

Then look outside the deletion boundary: a pg_dump file on a laptop, a staging or preview database, CI seed data, a warehouse or BI extract, a spreadsheet export a teammate made, and the records your payment and email providers hold. Rebuilding from those is partial, so note which tables each source can refill.

Restore into a copy, not over production

A separate restore keeps the damaged source for investigation, lets checks run without live writes, and leaves a second try if the recovery point was wrong. Provider behavior differs. On Supabase, an in-place restore leaves the project “inaccessible during this process”, while Restore to a New Project needs physical backups on the source and “creates a database-only copy”. A restore to another Supabase project does not bring every non-database service with it: storage files, Edge Functions, auth settings and API keys are among the items it does not copy.

Railway’s point-in-time recovery provisions a new Postgres service beside the source and leaves the source untouched. On Railway’s volume backups, a restore mounts a newly restored volume and keeps the previous one unmounted; backups newer than the restore point are not copied to the new volume, but they are not deleted either. Where only an in-place restore exists, take a snapshot or export of the damaged state first if support confirms that is safe. Values that were changed rather than removed are a different recovery: data that was overwritten rather than deleted.

Check the restored copy before traffic returns

A green restore status says the job finished, not that the app works. Run six checks on the copy:

  1. 01 The schema version matches the app version you will deploy.
  2. 02 Critical tables exist, constraints validate, and recent row counts look plausible.
  3. 03 Auth records and access policies match the recovered schema.
  4. 04 Rows that point at files, queues or third-party objects still point at real ones.
  5. 05 One complete workflow works from the screen to the database and back.
  6. 06 Workers stay paused until you know they cannot replay stale jobs.

Then pick the reconciliation window, from the restored timestamp to the moment writes stopped, and rebuild what you can from payment, email and webhook records. Make every replay idempotent, so nothing charges a card or sends an email twice. If the restored copy will not take writes, the causes are in a restored database that refuses writes.

How to stop it happening again

Preventing a repeat takes boundaries, not more care: one database and one scoped token per environment, a read-only default login for people and agents, deletion protection or a recovery window on the project, and a backup copy kept outside the provider account, proven by a timed restore drill.

Start by writing down the recovery time and the data loss you actually had, since those two numbers set what the boundaries must achieve. Then build these this week:

  • One database and one API token per environment, each scoped to one project, and no token reused from another purpose.
  • A read-only role as the default login for people and agents, with a write role taken on purpose for the minutes it is needed.
  • Know the provider’s safety net for deletes: Neon lets you recover deleted projects for 7 days, and on paid plans a protected branch cannot be deleted and neither can its project; Railway soft-deletes volumes for 48 hours; a deletion-protection setting is not stated in Railway’s or Supabase’s docs.
  • A Postgres event trigger on ddl_command_start that raises an error for DROP from the app’s role. It guards objects inside the database, not the database itself, and the manual says only superusers can create one.
  • The environment name on screen before you type: a shell prompt or a psql prompt that prints the target.
  • A pg_dump copy on a schedule, stored outside the provider account, with an alert when the job stops.
  • A timed restore drill on the calendar.

The manual’s own words on PostgreSQL event triggers are that the event “does not occur for DDL commands targeting shared objects”, databases among them, and that when a ddl_command_start trigger fails with an error, “no attempt will be made to execute the command itself.” The plan around these boundaries and the timed drill are in the disaster recovery checklist for SaaS, and who can connect and which role the app uses are in how to harden managed database settings.

Common questions about losing production data

How to recover data that wasn’t backed up?

Recover it from copies that live outside the database: exports, pg_dump files on laptops, staging or preview databases, CI seed data, warehouse extracts, and the records payment and email providers hold. On a managed host, also ask support at once whether any storage still exists. Supabase’s backups docs cover daily backups on Pro, Team and Enterprise only and tell free tier projects to export their data themselves.

What command deletes a database?

In PostgreSQL, DROP DATABASE deletes a whole database: it removes the catalog entries and “deletes the directory containing the data”, and only the database owner can run it. DROP TABLE removes tables, TRUNCATE removes all rows from a set of tables, and DELETE with no WHERE clause deletes every row and leaves “a valid, but empty table.”

Which AI deleted database recently?

Cursor’s agent running Anthropic’s Claude at PocketOS in April 2026, and Replit’s Agent in a case Replit described in July 2025. The PocketOS founder said the agent deleted a Railway volume holding the production database and its volume-level backups; Railway later wrote, without naming the customer, that it had recovered the database. In its post of 29 July 2025, Replit wrote that its Agent “deleted data from the app’s database” of SaaStr co-founder Jason Lemkin, who was eventually able to use rollback “to fully restore his database”; Replit added that Agent “was completely unaware” that rollback existed.

How to completely delete a database?

Run DROP DATABASE as the database owner while connected to a different database, or delete the project on a managed host, which on Supabase also removes the backups and cannot be reversed by its support. Take an export first if anything in it may be needed later, because once either runs there is no undo on your side.