RDS backups and EBS snapshots without AWS: the boring stack

TL;DR. Two of the scariest things to give up when you leave AWS are RDS automated backups (with point-in-time recovery — rewind the database to any second before a mistake) and EBS volume snapshots. Both reproduce cleanly on a plain OVH or Hetzner server with mature, boring open-source tools: pgBackRest streams full + incremental + WAL backups of Postgres to any S3-compatible bucket with built-in retention (true PITR); ZFS + sanoid/syncoid gives you instant, scheduled, auto-expiring volume snapshots replicated offsite (the real EBS-snapshot analog); restic or BorgBackup handle files. You even get two things AWS doesn’t hand you by default: immutable, ransomware-proof backups (object-lock / WORM) and cheap or free restore egress. The honest caveat: managed RDS backups are labor you no longer do — for a team with zero ops capacity, that convenience can be worth paying for.

The fear, named

Leaving AWS, the database is where nerve fails. RDS quietly takes a snapshot every night, lets you rewind to any second in the retention window, and replicates it across zones — and EBS snapshots do the same for whole volumes. Run your own server and you own that now. The good news: this is one of the most solved problems in operations. The tools below are what banks and hosting companies have used for a decade. None of it is exotic.

There are two separate jobs, and people conflate them:

  1. Database backups — logical/physical backups of Postgres/MySQL with point-in-time recovery. (The RDS part.)
  2. Volume / block images — a frozen image of an entire disk you can roll back or clone. (The EBS part.)

You want both. They use different tools.

Part 1 — RDS-style database backups with point-in-time recovery

Postgres: pgBackRest (the direct RDS replacement)

pgBackRest is the gold standard. It does full + differential + incremental backups, archives WAL for point-in-time recovery, pushes straight to S3-compatible object storage, encrypts client-side, runs in parallel, and has retention/expiry built in:

# /etc/pgbackrest/pgbackrest.conf  (illustrative — verify against the docs)
[global]
repo1-type=s3
repo1-s3-bucket=db-backups
repo1-s3-endpoint=<r2-or-b2-or-hetzner-endpoint>
repo1-s3-region=auto
repo1-path=/pg
repo1-cipher-type=aes-256-cbc          # client-side encryption
repo1-retention-full=4                  # keep 4 full backups, expire older
repo1-retention-diff=12

[main]
pg1-path=/var/lib/postgresql/16/main

Schedule with a systemd timer (or cron):

# nightly full on Sunday, incremental the other days
pgbackrest --stanza=main --type=full backup     # Sun
pgbackrest --stanza=main --type=incr backup     # Mon–Sat

Restore to a point in time is one command:

pgbackrest --stanza=main --type=time \
  --target="2026-06-15 14:30:00" restore

That’s RDS’s headline feature — nightly backups + PITR — on storage you control. Lighter alternatives: pg_dump (logical, no PITR — fine for small DBs), Barman (another full PITR manager), or WAL-G (popular, S3-native, also does MySQL/MongoDB).

MySQL / MariaDB

Same shape, different tool: mariabackup / Percona XtraBackup (physical, hot, supports incremental + binlog for PITR) or mydumper (fast parallel logical dump). Pipe the output to object storage on a timer.

Where the backups go

Any S3-compatible bucket — and this is where the cloud-exit math shows up again:

Backup targetStorageRestore egressNotes
Cloudflare R2~$15/TB-mo$0Zero egress = free disaster recovery
Backblaze B2~$6/TB-mofree up to 3× storedCheapest storage
Hetzner Object Storagelow, included-ish transfercheapSame vendor as the box — keep one copy elsewhere
OVH Object StoragelowcheapDitto
MinIO / SeaweedFS (self-host)your diskfree (LAN)Good as the first local copy
AWS S3 (for comparison)~$23/TB-mometered ($0.09/GB)Restoring a 1 TB DB = ~$90 just in egress

The quiet win: on AWS, restoring a large backup is metered egress and cross-AZ — you pay to get your own data back in a disaster. On R2/B2/Hetzner that restore is free or near-free. Your DR drill stops being a line item.

Part 2 — EBS-snapshot-style volume images (this is where filesystem choice matters)

A database backup protects the database. A volume snapshot protects the whole disk — config, the OS, an app’s data dir — and lets you roll back or clone in seconds. On AWS that’s EBS snapshots; on your own box it’s a copy-on-write filesystem, and yes — ZFS is the smart choice.

ZFS + sanoid + syncoid (the real EBS-snapshot analog)

zfs snapshot is instant, atomic, copy-on-write — a point-in-time image of a dataset at near-zero cost. Two companion tools turn that into a full snapshot-and-replicate system:

# /etc/sanoid/sanoid.conf
[tank/pgdata]
  use_template = production
[template_production]
  hourly = 24
  daily  = 30
  weekly = 8
  monthly = 12
  autosnap = yes
  autoprune = yes
# replicate hourly to an offsite box (run from a timer)
syncoid tank/pgdata backup@offsite:tank/pgdata

Bonuses EBS doesn’t give you: checksums (catches silent corruption), lz4 compression (~free), encryption at rest, and atomic snapshots of a running database (combine with a quick checkpoint for app-consistency).

Alternatives

Part 3 — files and everything else: restic / Borg

For application files, uploads, configs (anything that isn’t a database or a whole volume), restic or BorgBackup are the de-facto standard: dedup, encryption, and retention built in — pointed straight at object storage.

restic backup /srv/app/data
restic forget --keep-daily 7 --keep-weekly 4 --keep-monthly 12 --prune

restic speaks S3/R2/B2 natively; that forget --prune is your auto-expiry.

Which filesystem should the server use?

Put together: the boring backup stack

What AWS gives youWhat you run instead
RDS automated backups + PITRpgBackRest (or WAL-G / Barman) → R2 / B2 / Hetzner, retention in-tool
EBS snapshots / AMIsZFS + sanoid (local, fast) + syncoid (incremental offsite) — or provider snapshots
File/volume backuprestic / Borg → object storage, forget --prune
Cross-region snapshot copysyncoid to a box at a different provider
Backup Vault Lock (immutability)S3 Object Lock / WORM on R2 / B2 / MinIO
Backup scheduling windowssystemd timers (or cron)

Follow 3-2-1: at least 3 copies, on 2 kinds of media/location, 1 of them offsite — and make 1 immutable (object-lock), so a compromised host can’t delete or encrypt your backups. That last point is a genuine upgrade over a default RDS setup, not a compromise.

Test your restores (the part everyone skips)

A backup you’ve never restored is a hope, not a backup. On owned infra this is easier than on AWS, because restore egress is free:

When managed RDS backups are genuinely worth keeping (be honest)

This isn’t free — it’s cheaper and more controllable, which is different. (Backups are only one slice of “managed” — for automatic failover, HA and version upgrades, see Managed database without AWS.) Stay on managed when:

For most small and scale-up teams with even basic Linux skill, the stack above is a few days of setup for a backup system you fully own — and a restore that doesn’t bill you egress to recover from a bad day.

Quick wins you can do this week

  1. Stand up pgBackRest against a cheap B2/R2 bucket; take one full backup; do one PITR restore into a container to prove it.
  2. If the box is ZFS (or can be), enable sanoid with a sane policy and syncoid to one offsite target.
  3. Turn on Object Lock on the backup bucket so backups are immutable.
  4. Add a restore drill to your calendar. Untested backups don’t count.

Designing this — the right filesystem, the retention policy, where the offsite copy lives, and the honest call on what to keep managed — is part of a Cloud-Exit Assessment. Or send me your cloud bill and I’ll show you what RDS/EBS/snapshot lines are costing you and what the owned equivalent runs, free, in 24 hours. Read by me, never shared.

Sources

Don't miss new posts

I publish honest, sourced breakdowns of cloud-exit economics — egress, storage, monitoring, reliability — and the occasional announcement. Leave your email and I'll let you know when something new goes up.

Double opt-in — you'll get one email to confirm. No spam, unsubscribe anytime. Read by me, never shared.