How to back up your Lovable or Supabase app (and actually test the restore)
7 July 2026· 3 min read · by Stackbastion
Lovable Cloud now includes daily backups. They’re kept for 14 days. That’s a real improvement over having nothing. But a backup you’ve never restored is a rumor, not a backup. And 14 days doesn’t cover everything. A bug can corrupt data quietly for three weeks before anyone notices. Here’s how to set up a backup you can actually trust, on your own Postgres instance.
Why daily snapshots aren’t the same as real backup
A daily snapshot only protects you against things you notice within 14 days. It also usually restores to last midnight, not to the exact moment before something went wrong. Point-in-time recovery, or PITR, fixes both problems. You keep a longer history. And you can restore to any second, not just to last night.
Step 1: set up continuous backup with PITR
If you run your own Postgres, pgBackRest is the standard tool for this. Here’s the pattern: a full backup on a schedule. Smaller backups in between. And a constant stream of write-ahead logs, so you can replay to any moment.
# One-time: initialize the backup repository
pgbackrest --stanza=main --repo1-path=/var/backups/pgbackrest stanza-create
# Weekly: full backup
pgbackrest --stanza=main --type=full backup
# Nightly: incremental backup
pgbackrest --stanza=main --type=incr backup
Add this line to postgresql.conf: archive_command = 'pgbackrest --stanza=main archive-push %p'. Now every log gets saved as it’s written, not just at backup time.
Step 2: get a copy off the server
A backup on the same machine as your database protects you against nothing. If that machine dies, the backup dies with it. Point pgBackRest’s storage at somewhere else: an S3-compatible bucket, or a provider like Hetzner Storage Box. Encrypt it while you’re there.
# repo1-cipher-type=aes-256-cbc in pgbackrest.conf, with a real passphrase
# repo1-path pointed at your off-server storage, not local disk
Step 3: the part everyone skips — actually test a restore
This step turns “I think we have backups” into “I know we have backups.” Restore to a separate, isolated copy. Never restore over your live database:
# Restore to a fresh, isolated data directory — never over the live one
pgbackrest --stanza=main --type=time \
"--target=2026-07-16 14:30:00" \
--pg1-path=/var/lib/postgresql/restore-test \
restore
Start Postgres against that restored copy. Run a query for a row you know should be there. Time the whole thing. That number is your real recovery time. Not a guess.
Step 4: set up dead-man’s-switch alerting
A backup that quietly stopped running three weeks ago is worse than no backup at all, because you think you’re covered. Have each successful backup ping a heartbeat monitor — a simple cron job hitting a health-check URL works fine. Send an alert if a heartbeat is missed for more than 24 hours.
Or, we do it for you
Setting this up correctly, restore drill included, is part of every Stackbastion plan — see what’s included. It’s also the core of our Full Production Rescue + Migration, if you’d rather have someone else do the migration.
FAQ
Do I need PITR if I already have daily snapshots?
Daily snapshots are better than nothing. But they only cover 14 days, and they only restore to midnight. PITR gives you a longer window and a more exact restore point.
How often should I actually run the restore test?
Do it once when you first set things up. Do it again any time you change your schema. After that, once a month is a fair pace for a small app.
What’s a reasonable recovery time for a small app?
There’s no single right answer. It depends what your users expect during an outage. Time your own restore first. Then decide if that number is good enough.