cd ../blog

23 Oct 2026 · 3 min read · Ravi Sanchala

Why I run two backup strategies, not one

Continuous backups and daily dumps protect you from different failures. And the backup doesn't count until you've restored from it.

postgresqlbackupsreliability

People are often surprised that I set up two independent backup systems for the same PostgreSQL database. Isn’t one enough?

One is enough for the failure you planned for. Two covers the failure you didn’t.

Different failures need different backups

Think about what actually goes wrong with databases:

What happensWhat you need
The server diesA recent copy somewhere else
Someone runs a bad DELETE at 14:32The database as it was at 14:31
Data slowly gets corrupted over weeksA clean copy from before it started
You need to move to a new server or versionA portable copy you can load anywhere
The backup tool itself has a bugA second copy made a different way

No single backup method handles all five well. So I use two.

Strategy 1: continuous backups with point-in-time recovery

PostgreSQL writes every change to its write-ahead log (WAL) before applying it. A tool like WAL-G ships those logs, plus regular base backups, to cloud storage continuously.

That lets you restore the database to any moment in the retention window, down to the second. On the setups I run, that window is 30 days.

This is what saves you from the bad DELETE. You restore to one minute before it happened.

Weak spot: it’s a physical copy. It’s tied to the PostgreSQL major version, and if corruption is written into the database, it’s faithfully shipped to the backups too.

Strategy 2: daily logical dumps

Once a day, pg_dump exports the database as SQL-level data. I keep those for 14 days.

A dump is portable. You can load it into a different server, a newer PostgreSQL version, or a laptop to investigate something. It’s also produced by a completely different mechanism than the WAL backups, so a bug in one doesn’t affect the other.

Weak spot: you can only go back to the moment the dump ran, so you can lose up to a day of changes.

Together, the two cover each other’s gaps.

Keep backups away from the thing they back up

A backup on the same disk as the database protects you from nothing that matters. Both strategies write to object storage (a bucket in a different service from the server), with access limited to the backup process.

A backup you haven’t restored is a guess

This is the part most teams skip.

Schedule restore tests. Restore the latest backup into a throwaway database, run a few queries to check the data looks right, and record how long it took. That number is your real recovery time, and it’s usually longer than people think.

I wrap both backup and restore in Make recipes, so they’re one command each and anyone on the team can run them:

backup-db:   ## Take a logical backup now and upload it
	./scripts/pg-dump-upload.sh

restore-db:  ## Restore a backup into a scratch database (BACKUP=name)
	./scripts/pg-restore-scratch.sh $(BACKUP)

Watch the backups themselves

Backups fail silently. A full disk, an expired credential or a changed bucket policy can stop them without anyone noticing.

Alert on backup age: if the newest backup is older than expected, someone hears about it today, not on the day you need it.

The short version

  • Continuous backups for “undo the last hour”
  • Daily dumps for “give me a portable, independent copy”
  • Both stored away from the server
  • Restores tested on a schedule
  • An alert when a backup is late

It’s boring. That’s the point.

related case study From hand-built servers to multi-country infrastructure, entirely as code read case study →

$ ./book-call.sh

Dealing with something like this?

Let's talk it through. 30 minutes, free, and you'll leave with a clear picture of what to fix first.

Book a free 30-min callOr take the free 3-minute scorecard

next post

Your Lovable MVP isn't production-ready yet. Here's the checklist. AI app builders get you to a working product fast. Here's what they don't give you, and what to fix before real users and real data arrive. Read post →