{"post":{"slug":"backup-verification-2026","title":"Backup Verification: A Backup You Have Not Restored Is a Guess","excerpt":"Backup jobs report success by writing a file. Whether that file can be restored into a working database is a different question, and it is the only one that matters.","category":"code","date":"January 6, 2026","author":"ByteLedger Team","content":"<span class=\"dropcap\">T</span>he backup job has succeeded every night for two years. The monitoring is green. Nobody has ever restored one.\n\nThat is not a backup strategy; it is a file-writing strategy with a strong assumption attached. The failure modes are numerous and all silent: the backup excludes a schema added last year, archives stopped being retained after a configuration change, the encryption key is not stored anywhere recoverable, or the file is complete and corrupt.\n\nEvery one of those reports success, and every one is discovered during an incident.\n\n## What changed in 2026\n\n- **Automated verification became standard practice.** Scheduled restore-and-validate pipelines moved from advanced to expected.\n- **Managed platforms added verification features.** Some services began offering automated restore testing.\n- **Recovery time entered service objectives.** Measuring restore duration became part of defining reliability targets.\n- **Ransomware raised the stakes.** Immutable backups and verified recoverability became a mainstream concern rather than a specialist one.\n\n## What a successful job does not prove\n\n| Job reports | Actually verified |\n| --- | --- |\n| Backup completed | A file was written |\n| No errors | The process did not crash |\n| Expected file size | Roughly the right amount of data |\n| Checksum matches | The file is intact as written |\n| — | The file restores |\n| — | The restored database works |\n| — | It contains what you need |\n| — | How long it takes |\n\nEverything below the line requires actually restoring. Nothing above it does.\n\nThe gap that catches people most often is coverage: a backup that has been running successfully for two years may not include the tables, schemas, or extensions added since it was configured.\n\n## Automate it\n\nVerification requiring someone to remember does not happen. The only reliable approach is a scheduled pipeline.\n\nThe shape: take the latest backup, restore it to a temporary instance, run validation checks, record how long it took, tear the instance down, and alert on failure.\n\nFrequency depends on how much change your system sees. Weekly is a reasonable default; daily for systems where the backup configuration changes often. The important property is that it runs without anyone deciding to run it.\n\nCost is modest — a temporary instance for the duration of a restore — and small against the cost of discovering a bad backup during an outage.\n\n## Validate the data, not just the restore\n\nA restore completing tells you the file was readable. It does not tell you the data is right.\n\nUseful checks after restore:\n\n**Row counts against expectations** for key tables. A restored database with an empty orders table completed successfully and is useless.\n\n**Recent data present.** Query for something written shortly before the backup. This catches archives that stopped being retained.\n\n**Schema completeness.** Every expected table, index, constraint, and extension. Catches coverage drift.\n\n**Application-level smoke test.** Point a test instance of your application at the restored database and exercise a few paths. Catches problems no data check would.\n\n**Duration recorded.** Recovery time is a number you should know in advance, and it changes as data grows.\n\nThat last one deserves emphasis. Teams frequently have a recovery time objective and no measurement of actual recovery time. The gap is discovered when it matters.\n\n## Common mistakes\n\n- **Treating job success as verification.** It proves a file exists.\n- **Manual verification.** It stops happening.\n- **Checking only that the restore completed.** Not that the data is correct.\n- **Not measuring duration.** Recovery time unknown until an incident.\n- **Backups on the same infrastructure as the database.** One failure takes both.\n- **Encryption keys stored only in the system being backed up.** Unrecoverable backups.\n- **No test of point-in-time recovery specifically.** Restoring the latest backup is not the same operation — see [point-in-time recovery](/blog/point-in-time-recovery-2026).\n\n## FAQ\n\n**How often should I verify?**\nWeekly as a baseline, more often if your schema or backup configuration changes frequently. The key property is automation rather than the exact interval.\n\n**Can I verify without a full restore?**\nPartially — file integrity checks catch corruption. They do not catch coverage gaps, missing archives, or unusable output. Only a restore proves a restore.\n\n**What about very large databases?**\nRestore cost is real at scale, and so is the risk. Options include verifying a subset regularly and the whole thing periodically, or restoring to cheaper storage. Not verifying because it is expensive is the wrong conclusion.\n\n**Should I test the runbook too?**\nYes — a verified backup with an unpracticed recovery procedure still produces a slow, error-prone incident. That is what a restore drill is for — see [restore drills](/blog/restore-drills-2026).\n\n## Where to go next\n\nFor practising the human side, read [restore drills](/blog/restore-drills-2026). For the recovery mechanism itself, [point-in-time recovery](/blog/point-in-time-recovery-2026), and for testing failover separately, [failover testing](/blog/failover-testing-2026).","hue":313,"metaTitle":"Backup Verification: An Untested Backup Is a Guess","metaDescription":"Why successful backup jobs do not prove recoverability, how to automate restore verification, and what to check beyond the restore completing.","keywords":["backup verification","restore testing","backup validation","recovery time measurement","automated restore","backup integrity","disaster recovery testing","database operations 2026"],"tldr":["**A successful backup job proves a file was written** — not that it can be restored.","**Restore automatically on a schedule** — verification that requires human effort does not happen.","**Check the data, not just that the restore completed** — row counts and checksums against expectations.","**Measure how long it takes** — recovery time is a number you should know before an incident.","**Skip:** verifying by inspecting the backup file. Only a restore proves a restore works."],"readTime":"4 min read","wordCount":805},"related":[{"slug":"restore-drills-2026","title":"Restore Drills: Practising Recovery Before You Need It","excerpt":"Verified backups prove the data can come back. A drill proves your team can bring it back, under pressure, using a procedure that has been read by someone other than its author.","category":"code","date":"January 9, 2026","author":"ByteLedger Team","readTime":"4 min read","hue":308},{"slug":"point-in-time-recovery-2026","title":"Point-in-Time Recovery: Undoing the DELETE You Regret","excerpt":"Replication copies your mistakes instantly. Point-in-time recovery is the only mechanism that lets you go back to just before someone ran a DELETE without a WHERE clause.","category":"code","date":"January 4, 2026","author":"ByteLedger Team","readTime":"4 min read","hue":304},{"slug":"failover-testing-2026","title":"Failover Testing: Finding Out Before Production Does","excerpt":"Automatic failover is configured and has never fired. Whether it works, how long it takes, and whether your application reconnects are all unknowns until you trigger it deliberately.","category":"code","date":"January 12, 2026","author":"ByteLedger Team","readTime":"4 min read","hue":308}],"sameCategory":[{"slug":"bazel-build-explained-2026","title":"Bazel Explained: What Hermetic Builds Actually Cost","excerpt":"Bazel delivers reproducible, precisely cached builds and demands that you describe everything. Here is what you get, what it costs, and who should say no.","category":"code","date":"August 19, 2026","author":"ByteLedger Team","readTime":"3 min read","hue":145},{"slug":"graphql-federation-2026","title":"GraphQL Federation: One Graph, Many Teams","excerpt":"Federation composes independently-owned subgraphs into a single API. Here is what it solves, the operational cost it adds, and when a simpler gateway is enough.","category":"code","date":"August 19, 2026","author":"ByteLedger Team","readTime":"3 min read","hue":300},{"slug":"hermetic-builds-explained-2026","title":"Hermetic Builds Explained: Same Inputs, Same Output","excerpt":"A hermetic build depends only on declared inputs. Here is what that property gives you, the common leaks that break it, and how to move toward it incrementally.","category":"code","date":"August 19, 2026","author":"ByteLedger Team","readTime":"3 min read","hue":130},{"slug":"monorepo-tooling-compared-2026","title":"Monorepo Tooling Compared: What You Actually Need","excerpt":"Monorepo tools solve task orchestration and caching, not repository layout. Here is what each tier provides and how to tell when you have outgrown the simple option.","category":"code","date":"August 19, 2026","author":"ByteLedger Team","readTime":"3 min read","hue":150}],"newer":{"slug":"autovacuum-tuning-2026","title":"Autovacuum Tuning: Keeping Cleanup Ahead of Churn","excerpt":"The background process reclaiming dead rows is fine until it is not. When it falls behind on a hot table, bloat grows, queries slow, and nothing in your application changed.","category":"code","date":"January 6, 2026","author":"ByteLedger Team","readTime":"4 min read","hue":310},"older":{"slug":"best-ai-voice-cloning-2026","title":"Best AI voice cloning tools in 2026: ElevenLabs vs Resemble vs Play.ht ranked","excerpt":"AI voice cloning got eerily good in 2026. Here's the honest ranking of the four tools worth paying for, with a note on the ethical line.","category":"ai","date":"January 6, 2026","author":"ByteLedger Team","readTime":"2 min read","hue":195}}