DEV Community

Cover image for I Deleted My Database on Purpose. It Was Back in 47 Seconds.
Vivian Chiamaka Okose
Vivian Chiamaka Okose

Posted on • Originally published at vivianokose.hashnode.dev

I Deleted My Database on Purpose. It Was Back in 47 Seconds.

There's a sentence I can't stop thinking about:

A backup you have never restored is a wish, not a backup.

Most engineers set up backups and never test them. The backup job runs every night, everyone feels safe, and then one day a real disaster hits, they reach for the backup, and discover it's been silently broken for months. Now the data is genuinely gone, at the worst possible moment.

So this week I stopped wishing. I destroyed my own database on purpose and proved I could bring it back.

First, I learned before I built

I did something different this module: I asked to understand the concepts before touching a single command. What a database actually is. Why SQL and NoSQL both exist. What containers really are. What migrations do.

It changed everything. Instead of copying steps and hoping, I knew why each command mattered. If you're learning DevOps and you find yourself typing commands you don't understand, stop and go learn the idea underneath. The labs land completely differently after that.

The stack, from one command

I built a four-container stack that starts with a single command: Postgres (the strict, organized store for important data), Redis (the fast, flexible one), Adminer (a web view of the data), and pgBouncer (connection pooling).

The stack, healthy

The stack, healthy II

The idea that made containers click for me: a container is a sealed lunchbox holding software plus everything it needs to run. It works identically on my laptop, your laptop, or a server in a data center. No more "but it works on my machine."

And one crucial piece: a volume. Containers are disposable, you throw them away and make new ones. A volume is the storage box that survives that. Without one, your data dies with the container. That distinction matters more than anything else in this setup.

Version control, but for your database's shape

Your database's structure changes constantly as an app grows. Add a column, add a table, add an index. The tempting way is to just log in and type the change. The problem: nobody has a record of what changed or when, and now your database, your teammate's, and production are all subtly different.

Migrations fix that. They're numbered, recorded files, V1, V2, V3, applied in order, with the tool keeping a history of exactly what ran and when.

Flyway applying migrations in order

They are, quite literally, git for your database structure. Which is why the concept felt instantly familiar after last month's Git module.

One detail worth stealing: I added a column in V2, and backfilled its values in V3, deliberately two separate migrations, not one. Because if an app is live while you change the database, adding and filling in one step means a moment where the app and database disagree. Additive first, destructive later. That staging is how you change a database without breaking the thing using it.

The refusal that impressed me most

Here's my favourite moment. In the real world, you almost never get to start a database from scratch. You inherit one that's been running for years, full of customer data you cannot wipe. So I simulated that: an existing database, real rows, no migration history.

I pointed the migration tool at it, and it refused:

Found non-empty schema but no schema history table.

It was saying: there's data here I didn't create, I don't know what version this is, and I won't guess and risk breaking it. That refusal is a feature. The tool protecting two years of data from a stranger's assumptions.

The fix is called baselining: you tell it "whatever exists now, call that version 1, count my changes from version 2." Like joining a company mid-project and saying "I'm not recreating what happened before I arrived. Today is my starting line."

That's the version of this skill you'll actually use at work.

Then I destroyed everything

The main event. Here's the drill:

  1. Count the rows: 3 authors, 3 posts
  2. Take a backup (8.2K file)
  3. Drop the entire database
  4. Restore it
  5. Verify the counts match
  6. Time it

Step 3 feels wrong to type. You're deleting the thing. And then:

The disaster

FATAL: database "lumberyard_dev" does not exist

That's the message on someone's screen at 3am when a room goes quiet. My data was genuinely gone.

Then I restored it from that 8.2K file.

Restore verified

3 authors, 3 posts. Exact match. Nothing lost. 47 seconds.

That number matters more than it looks. In a real incident, everyone asks "how long until we're back?" Most people guess. I can answer, because I measured it.

What I'd tell past me

Three things I actually learned, beyond the commands:

Check the file size. A zero-byte backup file is a silent catastrophe that only surfaces when you desperately need it. Always look.

"No errors" is not "it worked." Verify the row counts. A restore that finishes quietly but incompletely is worse than one that fails loudly.

Backups don't belong in git. I committed my dump file, then realized: backups contain real data, they bloat the repo forever, and in a real job that's publishing customer data. They belong in object storage. I removed it and gitignored *.dump. A small fix, but the instinct matters.

The real takeaway

Code is replaceable. You lose it, you redeploy from git. Data is not. Lose it and it may be gone forever.

Which is why the most valuable thing I did this week wasn't building the stack or writing migrations. It was deleting everything and proving I could get it back. Most junior engineers have never restored a backup. They've just trusted one exists.

Don't trust. Drill.

Next up: containers, properly.

Top comments (0)