Backups for Beginners: How to Not Lose Your App's Data
Your code is in Git. Your users' data isn't. What actually needs backing up, the 3-2-1 rule, why a backup you've never restored doesn't count, how often to back up, and a simple backup plan for a small app — including what to do before letting an AI agent near your database.
Losing data is one of the few mistakes that can end a small app overnight. A bad migration, an accidental delete, an AI agent running the wrong command, a provider outage, a ransomware attack — they all happen, and they all have the same cure: a recent backup you know how to restore.
What needs backing up?
Your app has several kinds of data, and they need different treatment:
| What | Where it lives | Backed up by |
|---|---|---|
| Code | Git / GitHub | Git itself, if pushed. (Git and GitHub for Beginners.) |
| Database | Your database server | You — or your provider, if you've checked |
| User uploads | Object storage or disk | You — often forgotten |
| Configuration and secrets | Environment variables, dashboards | A password manager or secure note |
| Third-party data | Stripe, your email provider | Mostly them — but know how to export |
The code is usually safe. The database and uploaded files are the irreplaceable parts — they're your users' work.
The 3-2-1 rule
A classic guideline that still holds:
- 3 copies of your data (the original plus two backups),
- on 2 different kinds of storage,
- with 1 copy somewhere else entirely — a different provider or region.
The idea is that no single failure — a deleted account, a provider outage, a bug that corrupts data and then gets backed up — takes out every copy.
For a small app, a practical version: your database, your host's automatic backups, and a regular export to storage at a different provider.
A backup you haven't restored isn't a backup
This is the most important sentence in this article. Backups fail silently all the time: the job stopped running months ago, the file is empty, the password to decrypt it is lost, or restoring takes three days nobody planned for.
Restore a backup to a test database at least once, and then regularly — a few times a year. Time how long it takes. Write down the steps. (Postgres Backup and Restore shows the commands for PostgreSQL.)
How often?
Ask: how much data could I stand to lose?
- Daily backups mean you could lose up to a day of changes.
- For many small apps, daily is a sensible minimum.
- If losing an hour of orders would be a disaster, you need more frequent backups — or point-in-time recovery, which lets you restore to any moment. (Postgres Point-in-Time Recovery.)
And ask: how long do I keep them? Keep at least a week or two of daily backups, plus some older ones (weekly, monthly). You won't always notice a problem the same day — sometimes data was quietly corrupted a week ago.
Check what your provider actually does
Managed databases often include automatic backups — but read the details:
- How often? Daily? Continuous?
- How long are they kept? Seven days is common on lower tiers.
- Can you restore it yourself, and to a specific time?
- What happens if you delete the database or the account? Some providers delete the backups too.
- Are uploads included? Usually not — file storage is separate.
If the answers aren't good enough, add your own backup on top.
A simple plan for a small app
- Turn on automatic database backups at your provider. Check retention.
- Add a scheduled export — a daily
pg_dump(or equivalent) copied to storage at a different provider. (Your App Needs Background Jobs covers scheduling.) - Back up uploads, with versioning turned on for your storage bucket if your provider supports it, so deleted or overwritten files can be recovered.
- Encrypt backups that leave your provider. They contain everything.
- Test a restore now, and put the next one in your calendar.
- Write down how to restore in your README or runbook, so it's not locked in one person's head.
Before risky changes, take a snapshot
Take a fresh backup right before:
- Running a database migration on production. (What Are Database Migrations?.)
- Bulk edits or deletes — "remove all test accounts."
- Letting an AI agent work with a database that holds real data.
AI coding agents are fast and confident, and "clean up the old records" can be interpreted more broadly than you meant. The best defence is not giving an agent production credentials at all — and having a fresh backup regardless. (How to Stop an AI Agent From Deleting Your Production Database.)
The checklist
- Automatic database backups are on; I know how long they're kept
- A second copy goes to a different provider
- Uploaded files are backed up or versioned
- Backups are encrypted
- I've restored one successfully, and know how long it takes
- Restore steps are written down
- I take a fresh backup before migrations and bulk changes
EasySpawn runs daily backups of every workspace, and the Team plan adds on-demand database backups — so you can snapshot right before a risky migration or an AI-driven change. See pricing or join the waitlist.
Related: Postgres Backup and Restore · What Is a Database? · Dev, Staging, and Production Explained
Keep reading
SQL Injection Explained: The Classic Attack and the One-Line Fix
SQL injection lets an attacker rewrite your database queries by typing into a form. How it works with a simple example, what damage it can do, why parameterized queries and ORMs prevent it, the places AI-generated code still gets it wrong, and how to check your app.
Password Hashing Explained: Why You Never Store Passwords
A well-built app doesn't know your password — it stores a hash. What hashing is, why fast hashes like MD5 and SHA-256 are wrong for passwords, what salts do, why bcrypt and Argon2 exist, and how to check that your AI-built app got it right.