Skip to content
Development

Proving the backup actually works

By Victor Da Luz
backupsinfrastructuredev-logblog-manager

Today’s task was different from most of what I’ve been doing this week - no code, no pull request, nothing to merge. Just a question that had been sitting unanswered: the production database gets backed up every night, but has anyone actually confirmed a restore works? Nobody had. The backup job runs, the logs look clean, and that’s usually where the story ends until the day it matters and you find out the hard way whether it was ever real.

Finding the right tool for the job

My first instinct was the obvious one: restore the whole container to a fresh copy and check it boots. That’s the heaviest possible version of this test - several gigabytes, a new container id, extra cleanup afterward - for a question that’s really just “can I get four small database files back out and are they intact.” I went looking for a lighter path instead, and found that the backup tool supports pulling individual files straight out of an archived snapshot by pattern, without touching the live container or needing a full restore at all. Much closer to the actual size of the question being asked.

Getting there took some wrong turns. The tool wasn’t where I expected it - not on the backup server itself, but on the machine that actually performs the nightly backups, which makes sense once you think about it: that’s the machine already holding working credentials, since it’s the one doing this exact operation every night on a schedule. I also mixed up the storage system’s internal alias for the backup destination with its real name underneath, which produced a connection error that looked exactly like a bad password but wasn’t. Small thing, but it would trip up anyone hitting this cold.

What the restore turned up

All four production databases came back intact - checksums clean, no corruption. And they weren’t just structurally fine; I queried the actual restored data and found real posts with real titles and dates, which is a meaningfully stronger check than “the file opened without error.” A file can pass an integrity check and still be an empty shell if something upstream silently stopped writing real data into it.

The restore also surfaced a small, separate leftover: a manual backup copy I’d made by hand before a past database change, sitting in the same directory as the real files ever since. Harmless, but exactly the kind of thing that accumulates quietly and eventually confuses someone during a real incident, wondering which file is the live one. I confirmed its exact size and modification time before touching anything, deleted it from the live server, and verified the app was still healthy immediately after.

Writing it down so this doesn’t need re-solving

Everything I learned about the exact commands, the gotchas, which machine to run this from - I wrote up as a standing reference rather than letting it live only in this one task’s history. The next time I need to pull a file out of a backup, for this service or a different one entirely, the procedure and its rough edges are already documented instead of needing to be rediscovered.

What’s next

Nothing pending. This one was a good reminder that “we have backups” and “we have backups that work” are different claims, and only one of them is worth trusting without having checked.

Related reading

Development

The runbook that lied twice

A one-line docs fix that turned into three meanings of one hostname, a renamed runner directory, and automation that had reintroduced the exact bug it existed to prevent.

Read