What Actually Gets Lost
When something goes wrong in a vibe coded app, most people reach for the same tool: the platform's rollback or restore point. It works, and it is the right first move — for code. A bad AI change that broke the checkout page is a code problem, and going back one version fixes it in a minute.
Data loss doesn't behave that way, and it usually doesn't announce itself. Here are the three shapes it takes:
- The change that ran against real data. You asked AI to "clean up the test accounts" or "fix the duplicate orders." It wrote a statement, the statement matched more rows than you pictured, and it ran against the live database. Nothing crashed. The app still loads. The rows are simply not there anymore.
- The container that disappeared. A project got deleted, a free plan lapsed and the database was paused and then removed, an account was suspended, or you cleaned up "the old one" and it was the current one. Here the code is fine and the data has no address.
- The quiet one. Nothing is broken. A customer says their order looks wrong, and you need to see what that record contained last Tuesday. Without history, you can only see what it contains now.
Rollback moves your code back to an earlier version. Restore brings your data back from a copy. They are different features, in different parts of your stack, and having one does not give you the other. An app that rolls back perfectly and has no data copy is one careless prompt away from being an empty app that works flawlessly.
The Three Backups You Need
A vibe coded app usually keeps its contents in three separate places, and each one has to be backed up on its own. Losing track of that split is why people think they are covered when they aren't.
- Your code. Almost always handled already — your builder keeps version history, or the project lives in a Git repository. This is the part people worry about most and lose least often.
- Your database. The rows: accounts, orders, posts, messages, settings. Hosted database providers offer automated snapshots, but you are responsible for knowing whether they are on for your plan and how far back they reach.
- Your uploaded files. Profile photos, attachments, exports, PDFs — these live in a storage bucket, not in the database. The database usually stores only the file's name or URL. A database backup restores a menu of filenames pointing at files that no longer exist. See the file uploads guide for how that split works.
There is a fourth thing that isn't data but will stop a recovery cold: your configuration. API keys, environment variables, webhook secrets, the domain settings, which email address owns which account. If the project itself is gone, restored rows won't run without them. Keep those in a password manager, not only in the platform's settings page — that page may be inside the thing you lost.
Turn On What Your Platform Already Gives You
Start with what you're already paying for. Open your database provider's dashboard and your storage provider's dashboard today, while nothing is wrong, and answer two questions for each:
- How far back can I go? If a bad change happened three weeks ago and you notice it now, is there still a copy from before it?
- How much would I lose? If a backup is taken once a day and the problem happens right before the next one, you lose up to a day of everything users did. Decide whether that number is acceptable for your app before you find out the hard way.
Then answer two more that people usually skip. Does it happen automatically, or only when I click? A backup that depends on you remembering is not a backup, it is a habit, and habits lapse exactly during the busy weeks when the data matters most. And where is the copy stored? A snapshot that lives inside the same project protects you from your own mistakes. It does not protect you from losing the project.
Look these up in your own dashboard, on your own plan, rather than trusting a tutorial or a forum answer. Backup retention is one of the first things providers change when they restructure their plans, and free tiers change most often of all.
Some hosted database free tiers pause inactive projects; others expire databases after a fixed window. A paused or expired database may be recoverable for only a limited time. If your app is a side project that goes quiet, do not assume its data or platform-managed copies will remain available indefinitely. Check your provider's current inactivity, expiration, backup, and recovery policies, and make sure at least one copy of your data lives somewhere those policies cannot affect it.
Your Own Copy, Off the Platform
Platform backups cover the common case. Your own export covers the case where the platform is the problem. You need one file you can open without logging into anything.
- Pick a format you can read without the vendor. A SQL dump, a CSV per table, or a JSON export. Open it once and confirm it actually contains rows. An export that is 400 bytes is not a small database, it is an empty one.
- Put the date in the filename and keep several.
app-2026-08-01.sql, notbackup.sql. A single file you overwrite every night is one bad night from being a perfect copy of the broken state. - Back up the files too. Download a copy of the storage bucket on the same schedule. Check whether your provider offers a command-line tool, API, or sync option for this.
- Choose a schedule you'll keep. Match it to how much you could stand to lose. A hobby app that gains a few rows a week is fine with a weekly export. Anything with paying users or content people can't retype should be daily and automatic.
- Store it somewhere the app account can't reach. A different cloud account, or an encrypted drive. The point is that one compromised or closed account should not take both the app and the backup.
Ask AI to build the export as one repeatable command rather than a set of steps you follow by hand:
Write me a single repeatable script that exports my [Postgres/MySQL/Firestore] database and my [S3/Supabase Storage/Firebase Storage] bucket to a local folder. Put the date in each filename so old exports are never overwritten. Read the connection string and credentials from environment variables — do not put them in the script. Print the row count per table and the total file size at the end so I can tell at a glance whether the export is complete or empty. Then use my providers' current official documentation to show me how to schedule it and calculate the egress or read-operation cost of running it daily. Cite each source, and state any missing input instead of guessing.
That file contains your users' email addresses, their content, and everything else they trusted you with — in plain, portable form, with none of the access controls your app enforces. Don't drop it in a shared folder, don't email it to yourself, and don't paste it into an AI chat to have the data "checked." Treat it exactly like the live database, because that's what it is. Sanitizing code and data before sending it to AI covers what changes once real user data leaves your app.
Before You Let AI Touch Data
Most vibe coded data loss doesn't come from a hack or a hardware failure. It comes from a helpful assistant executing a reasonable-sounding request against the only database you have. The tools make this easy on purpose: many builders connect straight to the live project, so there is no staging copy to make mistakes in.
Certain requests are more dangerous than they sound, because each one implies a delete or an update with a condition you never see: "clean up the test data," "remove the duplicates," "reset the demo accounts," "fix the broken rows," "start fresh." None of them name which rows. AI has to guess, and it will guess confidently.
Four habits remove almost all of this risk:
- Know what you're pointed at. Before any data change, confirm out loud whether this is the live database with real users in it. If you have only one database, the answer is always yes.
- Export first. Run your export command before the change, not after. This is the single step that turns a disaster into an annoying afternoon.
- Count before you delete. Ask for the matching rows as a count first. If you expect to remove 12 test accounts and the count says 1,847, you just avoided the whole problem for the price of one query.
- One change at a time. Run one statement, check the app, then move on. Batched data changes are hard to undo selectively, because you can't tell which one did the damage.
I want to [remove the test accounts / merge the duplicate orders / reset the demo data] in my live database. Do not run anything yet. First, show me the exact statement you would run, with the full WHERE clause. Second, show me a SELECT COUNT(*) using that identical WHERE clause so I can check how many rows it matches before anything changes. Third, tell me which other tables reference those rows and what happens to them — deleted, orphaned, or blocked. I will run the count myself and tell you the number before you do anything else.
A statement containing DELETE, DROP, TRUNCATE, or an UPDATE whose condition you have not personally read is a change you have not approved — no matter how clearly the chat explained it in the paragraph above. The dangerous version isn't the one that errors out. It's the one that runs, reports success, and matched the whole table because the condition was missing.
The Restore Drill
A backup you have never restored is not a backup. It is a file you believe in. The only way to convert it into something you can rely on is to use it once, deliberately, on a quiet afternoon when nothing is on fire.
The drill is short:
- Create a brand new, empty database or project. Never restore over the live one to "see if it works."
- Load your most recent export into it.
- Point a local copy of your app at the restored database and start it.
- Log in as a test user. Open the newest record you know should be there. Compare a few row counts against the live app.
- Open an uploaded file through the restored app, not just through the storage dashboard. This is the step that catches a missing bucket copy.
- Time the whole thing, and write down what you did.
Almost everyone discovers something the first time. The usual finds: the export ran but was empty because credentials had expired; the database export didn't include the user accounts, because hosted authentication is a separate system with its own export; the files were never in the backup at all; nobody remembered which account owned the storage bucket; or the export was of the wrong project entirely.
Finish by writing a short recovery note — a plain file with the links to each dashboard, where the exports are stored, which account owns them, and the steps you just performed in order. Keep it somewhere you can read when your app is down and you are not thinking clearly, which is the only time you will ever need it. Re-run the drill after any big change to your data or your hosting, and read how to fix a broken vibe coded app for what to do in the minutes before you reach for the backup.
Backup Checklist for a Vibe Coded App
- You know the difference between rollback and restore — code goes back one way, data the other.
- All three parts are covered — code, database, and uploaded files, each backed up separately.
- Keys and settings live in a password manager — not only inside the project you might lose.
- You've checked your actual plan — how far back the platform's backups reach, and how much data a gap between them would cost you.
- Backups run automatically — not when you remember.
- One copy lives outside the platform — a dated export in an account that isn't the app's account.
- You've opened an export and seen real rows in it — file size alone proves nothing.
- Exports are treated as production data — stored privately, never pasted into a chat.
- You export before every data change — especially the ones that sound like cleanup.
- You read the WHERE clause and check the count before any delete or update runs.
- You have restored once, into an empty project — and written down how long it took and what the steps were.
Related Guides
Growing Your Vibe Coded App
Adding features, handling real users, and keeping an eye on hosting and storage costs as your app grows.
How to Fix a Broken Vibe Coded App
What to do when the app stops working and you can't read the code — where to look, what to roll back, and how to describe the failure to AI.
Adding File Uploads to Your Vibe Coded App
Add photo and file uploads without writing files to your own server. Use hosted storage, validate what you actually received, and keep private files private.
Sanitizing Code and Data Before Sending to AI
What to scrub before pasting code or credentials into an AI conversation—including API keys and user-submitted data.