Skip to content

Grokem · https://www.grokem.com/databases/administration-and-tuning/backup-and-recovery/database-backup-restore-checklist

Backup & RecoveryBest practices

A database backup checklist that proves you can restore

A backup you have never restored is a hope. Twelve checks that turn backups into a recovery you can rely on, with the reason behind each.

Grokem Editorial

Editorial desk

Published
  • 4 min read

Almost every team has backups. Far fewer have restores, and the difference is only discovered on the worst day. This checklist is arranged in the order you would build it: decide what you need, protect it, then prove it works.

Start with two numbers

Without targets you cannot tell whether a backup is good enough.

  • Recovery point objective (RPO): how much recent data you can afford to lose, measured in time. An RPO of 24 hours means a nightly backup is enough. An RPO of five minutes means you need continuous log shipping, not a nightly dump.
  • Recovery time objective (RTO): how long you can be without the system. An RTO of four hours means a restore that takes six is a failure, however good the backup.

Ask the people who depend on the data, not only the people who run the database. The answers usually cost money, and that is the point of asking: the numbers turn a vague wish ("don't lose data") into something you can design for and test against.

What each item protects you from

The checks fall into four groups, and a gap in any of them is how recoveries fail in practice.

Know the target. The two numbers above, written down and agreed.

Back up the right things, in the right way. A copy that cannot be restored in a consistent state, or that is missing the keys, roles or configuration, looks fine until it is needed. Take backups with the database's own tools or a proper snapshot, never by copying the files of a running database.

Keep it safe. Backups are a target for attackers and a victim of the same failures as the system they protect. Separate copies, offsite storage, encryption and one immutable copy mean one incident cannot take both.

Prove it works. This is the group most often skipped. A restore test is the only evidence that everything above was done correctly, and it gives you the real recovery time instead of an estimate.

Taking a consistent backup

Every database has a supported way, and it is almost always better than copying files. In SQLite, Python's sqlite3 module exposes the online backup API, which copies a database that is in use. This script takes a backup and then checks it, which is the habit to copy:

python
import os
import sqlite3
import tempfile

folder = tempfile.mkdtemp()
live = sqlite3.connect(os.path.join(folder, "app.db"))
live.execute("CREATE TABLE orders (id INTEGER PRIMARY KEY, total REAL)")
live.executemany("INSERT INTO orders (total) VALUES (?)", [(10.0,), (25.5,), (7.25,)])
live.commit()

# 1. take a consistent copy while the database is in use
backup_path = os.path.join(folder, "app-backup.db")
copy = sqlite3.connect(backup_path)
with copy:
    live.backup(copy)
copy.close()

# 2. prove it can be restored: open the copy as if it were a new server and check it
restored = sqlite3.connect(backup_path)
print("integrity:", restored.execute("PRAGMA integrity_check").fetchone()[0])
print("rows:", restored.execute("SELECT COUNT(*) FROM orders").fetchone()[0], "| newest id:", restored.execute("SELECT MAX(id) FROM orders").fetchone()[0])
print("matches live:", restored.execute("SELECT SUM(total) FROM orders").fetchone() == live.execute("SELECT SUM(total) FROM orders").fetchone())
text
integrity: ok
rows: 3 | newest id: 3
matches live: True

The second half is the important part. A backup file that exists says nothing; one that opens, passes an integrity check and matches the live data is evidence.

For PostgreSQL the equivalent tools are pg_dump (a logical backup of one database) with pg_restore to load it, and continuous archiving of the write-ahead log for point-in-time recovery. A common pair of commands is:

bash
pg_dump --format=custom --file=app.dump appdb
pg_restore --list app.dump        # reads the dump and lists its contents: a quick sign it is not corrupt

A restore drill

Pick a quiet hour and rehearse the real thing:

  1. Restore last night's backup into an empty environment that is not production.
  2. Start the application against it.
  3. Check: row counts against the source, the newest record's date, a handful of real queries, and that people can sign in.
  4. Time the whole exercise from "go" to "working". That is your real RTO.
  5. Write down every step that was unclear or missing, fix the runbook, and book the next drill.

Using the list

Treat it as a review, not a one-off. For each line write down the current answer, who owns it and when it was last checked. The lines you cannot answer are your next tasks, and the order to tackle them is the order the list is in. The drill is the best test of the whole list at once: whatever it exposes is what to fix first.

Checklist

  • Write down the recovery point objective (how much data you can afford to lose, in hours) and the recovery time objective (how long you can be down). Every other choice follows from these two numbers.
  • Back up everything needed to rebuild: the database, but also its configuration, users and roles, schema migrations, and the encryption keys without which an encrypted backup is useless.
  • Keep at least one copy in a different place from the database: another account, region or provider. A backup on the same disk, or in the same account an attacker has taken over, is not a backup.
  • Follow the 3-2-1 idea: three copies, on two kinds of storage, one of them off-site. Add one copy that cannot be changed or deleted for a set time (immutable or offline) to survive ransomware and mistakes.
  • Use consistent backups. Take a snapshot or use the database's own backup tool, never a plain file copy of a running database, which can capture a half-written state.
  • Add continuous log archiving (point-in-time recovery) if you cannot lose a day of data. A nightly backup alone means losing up to a day.
  • Encrypt backups in transit and at rest, and store the keys somewhere that survives the loss of the system you are recovering.
  • Restore regularly into a separate environment, and check the result: row counts, the newest record, a few real queries and the application starting against it. Schedule this; a restore test that depends on someone remembering will not happen.
  • Time the restore. The number you measure is your real recovery time, and it is usually longer than the number in the plan.
  • Monitor and alert on backups: that the job ran, finished, produced a file of a plausible size, and that the newest backup is recent. Silence should be treated as failure.
  • Set retention deliberately: how many daily, weekly and monthly copies, how long for legal and business reasons, and when old ones are deleted. Check whether personal data in old backups is covered by your deletion obligations.
  • Write the runbook and keep a printed or offline copy: who decides to restore, the exact commands, where the keys are and who has access. Practise it on a quiet day.

Frequently asked questions

Is replication a backup?

No. A replica copies mistakes, deletions and corruption almost instantly. It protects against hardware failure, not against a bad query or a malicious change. Keep real backups as well.

How often should I test a restore?

At least quarterly for important systems, and after any change to the backup process or the database version. Automating a small restore test every week is better still.

References

From Grokem: https://www.grokem.com/databases/administration-and-tuning/backup-and-recovery/database-backup-restore-checklist

How did this strike you?

Be the first to react – it is anonymous.

Community

Questions about this?

Ask in Questions and help and get help from other readers.

Ask a questionBrowse Questions and help

Comments

No comments yet. Share what worked for you, or ask a question.

Choose what we may use. You can change this at any time with “Privacy choices” at the foot of every page. Details are in the Cookie policy and the Privacy policy.

Strictly necessary

Remembers your theme, the lessons you marked as done and this choice. It stays on your device, tracks nothing and cannot be switched off.

Always on
What exactly is collected, and why

Grokem’s own counts

Collects
The pages you open and how long you stay, how far you scroll, where you came from, your device type, browser, screen size, language and time zone. Your IP address is turned into a code that changes every day; it is never stored as it is.
Why
To see how long lessons are read and where readers leave. Not shared with anyone.
Stored
A random visitor ID, a visit ID and the time of your last page view in your browser’s storage (gr_vid, gr_sid, gr_last). No name or email is attached.