🛟 Cloud Backups and Disaster Recovery: Protect, Copy, Restore
Backup against snapshot against replication against disaster recovery, what each cloud's backup service offers (plans, vaults, retention, immutability, cross-region copies), how incremental backups and retention schedules really work (run for real), and why you only have a backup once you have restored one
💡 How this page was made. The mechanics were run for real on 6 October 2026 with GNU tar and Python, in a throwaway folder: a full backup and an incremental one, a restore chain checked with checksums, what a restore of only part of the chain gives, the retention schedule of a "gold" policy, and recovery-time arithmetic (the throughput figures there are illustrative, not measured on a cloud). The services and their settings are from the providers' documentation, read on 6 October 2026: AWS Backup, Azure Backup, Google Cloud snapshot schedules and Backup and DR, and Oracle block volume backups. Nothing was run on a cloud account. The same lesson, with a real two-machine routine and a destroyed-and-restored dataset, is on the FreeBSD Corner's ZFS backups page. Related: IAM, cost control, EC2 (snapshots) and Terraform.
Four words that get mixed up
- Snapshot: a point-in-time copy of a disk or volume, usually on the same cloud, often in the same account. Fast and cheap, great before a risky change. It protects against mistakes, but if the account is lost, locked or attacked, the snapshots may go with it.
- Backup: a copy kept apart from the original, with its own retention rules and, ideally, its own access rules. It protects against mistakes, corruption, ransomware and deletion.
- Replication: keeping a live copy somewhere else (another zone, another region). It protects against hardware and site failure, and it copies your mistakes too: delete a table, and the replica deletes it a moment later. Replication is not a backup.
- Disaster recovery (DR): the plan and the machinery to run the service somewhere else when its home is gone. Azure's documentation draws the line cleanly: its backup service is for backup and restore, while failover orchestration is another product, Azure Site Recovery.
Two numbers define what you need:
- RPO (recovery point objective): how much data you can afford to lose, measured in time. A backup every 24 hours means up to a day of data lost.
- RTO (recovery time objective): how long the service can be down while you restore.
The arithmetic (as run; the transfer speeds are examples, not measurements):
>>> def worst_case_loss_hours(interval_hours, backup_minutes=20):
... return interval_hours + backup_minutes / 60
...
>>> for h in (24, 6, 1):
... print('backup every %2d h: you can lose up to %.1f h of data' % (h, worst_case_loss_hours(h)))
...
backup every 24 h: you can lose up to 24.3 h of data
backup every 6 h: you can lose up to 6.3 h of data
backup every 1 h: you can lose up to 1.3 h of data
>>> def restore_hours(size_gb, mb_per_s, fixed_minutes=15):
... return size_gb * 1024 / mb_per_s / 3600 + fixed_minutes / 60
...
>>> for size, speed in ((100, 100), (1000, 100), (1000, 400), (10000, 400)):
... print('%5d GB at %3d MB/s -> about %.1f h to restore' % (size, speed, restore_hours(size, speed)))
...
100 GB at 100 MB/s -> about 0.5 h to restore
1000 GB at 100 MB/s -> about 3.1 h to restore
1000 GB at 400 MB/s -> about 1.0 h to restore
10000 GB at 400 MB/s -> about 7.4 h to restore
- A backup every 24 hours can lose 24.3 hours of data (the interval plus the 20 minutes the backup takes), every 6 hours loses up to 6.3, every hour up to 1.3. RPO is set by how often you back up.
- Restore time is size divided by speed, plus a fixed amount of setup: 100 GB at 100 MB/s is about half an hour, 1 TB at 100 MB/s about 3 hours, 10 TB at 400 MB/s over 7 hours. RTO is set by how big the data is and how fast you can move it. A restore that you have never timed is a guess.
The 3-2-1 idea, in cloud terms
The classic rule: 3 copies of the data, on 2 kinds of storage, 1 off-site. In a cloud:
- The live data is copy 1.
- A backup in the same cloud and region (snapshots, the backup service) is copy 2.
- A copy in another region, and ideally in another account or vault with different administrators is copy 3, and the one that survives a regional outage, a deleted account or an attacker with your credentials.
- For data you cannot lose: a copy outside the cloud provider, because a provider account can be suspended, hacked or closed.
What each cloud offers
AWS: AWS Backup
A fully managed service that centralizes backups across AWS services. From the documentation:
- Backup plans: policies for schedule and retention, assigned to resources by tag so that new resources are protected automatically.
- Backup vaults: where backups are kept, separate from the source: the vault keeps your EC2 and EBS backups under your lifecycle policy even if you delete the source instance and volume.
- Incremental backups for supported resource types (the first is full, later ones store only the changes). Not every type supports it: for those, "each backup is a full copy, which can result in higher storage costs".
- Lifecycle: move older backups to a cheaper cold storage tier.
- Cross-region and cross-account copies, on demand or in the plan, "particularly valuable" when you need backups a minimum distance away. You can "fan in" to a single repository account.
- Vault Lock (a write-once-read-many, WORM, model) that can prevent anyone, including you, from deleting backups or changing their retention.
- Audit Manager reports on compliance, and activity goes to CloudWatch, EventBridge, CloudTrail and SNS.
- It covers EC2 (EBS-backed), EBS, S3, RDS and Aurora, DynamoDB, EFS, FSx file systems, EKS and more.
- You pay for backup storage, restores, restore testing, cross-region transfer and Audit Manager. AWS also notes that AWS Backup does not govern backups you take outside it, and that for some services (RDS continuous backups, DynamoDB) native backups and AWS Backup relate in different ways, so check for duplicate costs.
Azure: Azure Backup
A native service for backing up VMs, disks, files, SQL Server, SAP HANA, PostgreSQL, MySQL, Cosmos DB, Azure Files, blobs, AKS and on-premises systems. From the documentation:
- A backup policy sets the schedule and retention; backups are stored in a Recovery Services vault or Backup vault, which "acts as a security boundary". For Azure VMs it takes a snapshot and transfers the data to the vault without impacting production.
- Types: snapshot-based (fast), vaulted (copied to a vault for durability and isolation), both, and a vault-archive tier for rarely needed, long-retention points.
- Replication of the backup data: LRS (three copies in one datacenter), GRS (to a secondary region, the default and recommended) or ZRS (across availability zones).
- Protection against deletion and ransomware: soft delete (deleted backups are kept for a period), immutable vaults (recovery points cannot be modified or deleted) and RBAC on the backup resources.
- No charge for the data transferred in or out (except an offline initial import), and storage is pay as you use.
- Microsoft's design checklist: workload types, RPO and RTO, retention and compliance, vault layout across subscriptions and regions.
- Disaster recovery (failover) is Azure Site Recovery, a separate service.
Google Cloud: snapshot schedules and Backup and DR
Two layers:
- Snapshot schedules for Persistent Disk and Hyperdisk: hourly, daily or weekly, created as resource policies that you attach to disks (the schedule lives in the same region as the disk, and snapshots can be stored in a regional or multi-regional location you choose). From the console or gcloud you must always set a retention policy; through the REST API the retention can be left out, which means snapshots kept indefinitely, so be careful when you create schedules through the API or tools built on it.
- Backup and DR Service: a managed service for Compute Engine VMs, Persistent Disk, Filestore, VMware Engine, Cloud SQL, AlloyDB and databases such as Oracle, SQL Server and SAP HANA. Backup plans link workloads to backup vaults, which "enforce write once, read many (WORM) immutability and indelibility" with a minimum retention of up to 99 years, regional or multi-regional. Restores can be file-level, whole-workload, or cross-region and cross-project clones. Google distinguishes it from snapshots: centralized governance, application-consistent backups and immutable storage that go beyond snapshots.
Oracle Cloud: block volume backup policies
For block and boot volumes, Oracle gives predefined policies that you cannot change, and user-defined ones:
- Bronze: monthly (the 1st) and yearly (January), kept 12 months and 5 years.
- Silver: weekly (Sunday), monthly and yearly, kept 4 weeks, 12 months and 5 years.
- Gold: daily, weekly (Sunday), monthly and yearly, kept 7 days, 4 weeks, 12 months and 5 years.
- The predefined policies are now all incremental backups, which Oracle describes as functionally equivalent to full ones for recovery. User-defined policies can set your own frequency and retention, include scheduled full backups, and add cross-region copy (not available with the predefined ones). The copy in the other region has the same retention, you pay for storage in both regions plus data transfer, and you must give a separate encryption key for the destination region.
- Policy-based backups all expire eventually: to keep one indefinitely, make a manual backup.
- Scheduled backups can start hours late when the system is overloaded, so they are not guaranteed to run at the exact time.
- I did not read about immutability or locking for these block volume backups, so check Oracle's current documentation if you need it.
What "incremental" really means (run for real)
A full backup copies everything. An incremental one copies only what changed since the last one, so it is small and fast. That is how every cloud snapshot and backup service keeps frequent backups affordable. The catch is on the restore side. I built a small folder (three reports, a 1.3 MB text file of numbers and a 3 MB random "photo") and made a full backup with GNU tar's incremental mode:
user@lab:~$ ls -lR data | grep -v "^total" data: drwxrwxr-x 2 user user 4096 Oct 6 19:18 docs -rw-rw-r-- 1 user user 1288895 Oct 6 19:18 numbers.txt -rw-rw-r-- 1 user user 3000000 Oct 6 19:18 photo.bin data/docs: -rw-rw-r-- 1 user user 40 Oct 6 19:18 report-1.txt -rw-rw-r-- 1 user user 40 Oct 6 19:18 report-2.txt -rw-rw-r-- 1 user user 40 Oct 6 19:18 report-3.txt user@lab:~$ (cd data && find . -type f | sort | xargs sha256sum) > before-1.sha; wc -l before-1.sha 5 before-1.sha user@lab:~$ tar --listed-incremental=state.snar -czf level0.tgz data; ls -l level0.tgz -rw-rw-r-- 1432203 Oct 6 19:18 level0.tgz
Then I changed the data: edited one report, added a new one, deleted another, and made the second backup:
user@lab:~$ echo "REVISED" >> data/docs/report-2.txt; echo new > data/docs/report-4.txt; rm data/docs/report-3.txt user@lab:~$ (cd data && find . -type f | sort | xargs sha256sum) > before-2.sha user@lab:~$ tar --listed-incremental=state.snar -czf level1.tgz data; ls -l level0.tgz level1.tgz -rw-rw-r-- 1432203 Oct 6 19:18 level0.tgz -rw-rw-r-- 1 304 Oct 6 19:18 level1.tgz user@lab:~$ tar -tzf level1.tgz | grep -v "/$" data/docs/report-2.txt data/docs/report-4.txt user@lab:~$ tar -tzvf level1.tgz | cut -c1-12,30- drwxrwxr-x use 19:18 data/ drwxrwxr-x use 19:18 data/docs/ -rw-rw-r-- use 19:18 data/docs/report-2.txt -rw-rw-r-- use 19:18 data/docs/report-4.txt
- The full backup is 1,432,203 bytes. The incremental one is 304 bytes: it holds only report-2.txt (changed) and report-4.txt (new), plus the directory entries (which is where tar records that a file was deleted).
- That is why a cloud can take a snapshot every hour: after the first, each one stores only the changes.
Now the restores, and the part people forget:
user@lab:~$ mkdir r-l0; tar --listed-incremental=/dev/null -xzf level0.tgz -C r-l0 # restore only the first backup user@lab:~$ (cd r-l0/data && find . -type f | sort | xargs sha256sum) | diff - before-2.sha > /dev/null && echo IDENTICAL || echo 'DIFFERENT: the first backup alone is out of date' DIFFERENT: the first backup alone is out of date user@lab:~$ mkdir r-l1; tar --listed-incremental=/dev/null -xzf level1.tgz -C r-l1 # restore only the incremental user@lab:~$ find r-l1 -type f r-l1/data/docs/report-2.txt r-l1/data/docs/report-4.txt user@lab:~$ mkdir r-full; tar --listed-incremental=/dev/null -xzf level0.tgz -C r-full; tar --listed-incremental=/dev/null -xzf level1.tgz -C r-full # the chain, in order user@lab:~$ (cd r-full/data && find . -type f | sort | xargs sha256sum) | diff - before-2.sha && echo IDENTICAL: the chain restores the state of the second backup IDENTICAL: the chain restores the state of the second backup user@lab:~$ ls r-full/data/docs # report-3.txt was deleted after the first backup report-1.txt report-2.txt report-4.txt
- Restoring only the first backup gives data that is out of date: the checksums differ from the state at the second backup.
- Restoring only the incremental gives just the two changed files: not a usable copy.
- Restoring the chain in order (first the full backup, then the incremental) gives data whose checksums are identical to the state at the second backup, and the file deleted in between is gone, as it should be (report-3.txt is not in the list).
- Lesson: an incremental backup is only as good as the chain behind it. Cloud services hide the chain (you click "restore this point" and they rebuild it), and they protect the links for you. When a service says "deleting a snapshot may not reduce storage cost" (AWS says so for EBS snapshots), this is the reason: blocks used by later snapshots must stay. If you build your own backups from files like this, keep a new full backup regularly so that no chain is too long to trust.
Retention: how long, and what you can go back to
A retention policy decides which restore points exist. A common design is grandfather-father-son: many recent points, fewer older ones. Oracle's documented Gold policy (7 daily, 4 weekly, 12 monthly and 5 yearly) as a model, run for real:
>>> import datetime as dt
>>> today = dt.date(2026, 10, 6)
>>> days = [today - dt.timedelta(d) for d in range(0, 365 * 6)]
>>> keep = set()
>>> keep |= {d for d in days if (today - d).days < 7}
>>> sundays = [d for d in days if d.weekday() == 6]
>>> keep |= set(sundays[:4])
>>> firsts = [d for d in days if d.day == 1]
>>> keep |= set(firsts[:12])
>>> januaries = [d for d in firsts if d.month == 1]
>>> keep |= set(januaries[:5])
>>> len(keep)
25
>>> sorted(keep)[0], sorted(keep)[-1]
(datetime.date(2022, 1, 1), datetime.date(2026, 10, 6))
>>> def newest_before(target): return max(d for d in keep if d <= target)
...
>>> newest_before(dt.date(2026, 8, 20))
datetime.date(2026, 8, 1)
>>> newest_before(dt.date(2025, 3, 15))
datetime.date(2025, 1, 1)
>>> newest_before(dt.date(2023, 6, 30))
datetime.date(2023, 1, 1)
>>> (dt.date(2023, 6, 30) - newest_before(dt.date(2023, 6, 30))).days
180
- Counting overlaps (a January 1st is both monthly and yearly), the policy leaves 25 distinct recovery points instead of 28, from 1 January 2022 to today.
- How far back can you go, and how precisely? Wanting 20 August 2026 gets 1 August, the newest point before it. Wanting 15 March 2025 gets 1 January 2025, and wanting 30 June 2023 gets 1 January 2023: 180 days earlier. Old points are coarse. Retention is a decision about precision: yesterday to the day, last year to the month, five years ago to the year.
- Longer and denser retention costs more (stored data, and on some clouds an early deletion charge: AWS Backup lists early deletion in its billing), so the question for each dataset is how far back would we really need to go? Legal and compliance rules sometimes answer for you.
Protect the backups themselves
Attackers and mistakes target backups too. What the documentation gives you:
- Separate them from the source: a vault, a second account or subscription or project, different administrators (the IAM page). If one stolen key can delete both the servers and the backups, you have one copy.
- Immutability (WORM): AWS Vault Lock, Azure immutable vaults, Google Cloud backup vaults (retention up to 99 years). Soft delete (Azure) keeps deleted backups for a period.
- Encrypt them, with keys that live elsewhere (AWS Backup vaults use their own KMS key, so a backup does not share the key of the source; Oracle needs a separate key for a cross-region copy).
- Limit who can restore, too: a restore can overwrite production.
- Copy across regions (all four have a way, above).
The restore test (run for real)
The single most important habit: restore, and compare. The checks used above are small enough to automate:
(cd ORIGINAL && find . -type f | sort | xargs sha256sum) > before.sha # ... restore into a new, empty place ... (cd RESTORED && find . -type f | sort | xargs sha256sum) | diff - before.sha && echo IDENTICAL
A restore test worth doing, for each important system, at least twice a year:
- Restore to a new place (a new volume, a new database, a test account), never over the original.
- Compare: checksums of files, row counts or a known query of the database, a few real application checks.
- Time it, and compare with your RTO. AWS Backup has restore testing as a feature (and bills for it).
- Write down what you needed: keys, passwords, the order of steps, who has access. A backup you cannot decrypt, or restore because the one person with the key is away, is not a backup.
- Fix what you find, and test again.
Disaster recovery in one page
When a whole region (or account) is gone, the question is how quickly the service runs somewhere else. Common levels, from cheap and slow to expensive and fast:
- Backup and restore: backups copied to another region; you rebuild from them. Cheapest, with the longest RTO.
- Pilot light: the data replicates continuously and a minimal copy of the environment is ready to scale up.
- Warm standby: a smaller, running copy that takes over.
- Active-active: the service runs in two places at once. The fastest recovery, and the most expensive and complicated.
The tools named in the documentation: cross-region copies (AWS Backup, Oracle's copy policy, Google's cross-region clones, Azure's GRS vaults), and Azure Site Recovery for failover. And the infrastructure should be code (Terraform, first-boot files: cloud-init page) so that rebuilding the environment is a command and not a memory.
Common mistakes
- Snapshots only, in the same account, as the whole plan.
- Replication mistaken for backup.
- Never restoring. The backup job succeeding means the copy was made, not that it can be restored.
- A long incremental chain with no new full backup.
- Backups in the same account as production, with the same administrators.
- No retention thought: either everything forever (the cost grows) or too little (the problem is found after the window).
- Leaving the retention out when creating schedules through the API (Google Cloud then keeps snapshots indefinitely).
- Forgetting the data that is not on disks: databases (use the database backup features), object storage, configuration, secrets and DNS.
- Not backing up the keys. Encrypted backups need their keys somewhere safe and separate.
- An untimed restore that turns out to take days.
- Forgetting the cost of the copies, and of the second region.
What this page did not cover
Database-specific backup and point-in-time recovery, application-consistent backups in depth, backing up Kubernetes state (AKS and EKS backups exist and are named above), SaaS data (email, documents), ransomware response plans, and prices (read each provider's pricing page).
The cheat sheet
- Snapshot (a point in time, often same account) | backup (kept apart, retention, protected) | replication (a live copy, copies mistakes too) | DR (run it elsewhere). RPO = data you can lose (set by backup frequency). RTO = downtime you can accept (size over speed, plus setup).
- 3-2-1: three copies, two kinds of storage, one off-site (another region, another account, ideally another provider for crown jewels).
- Services: AWS Backup (plans, tags, vaults, Vault Lock, cross-region and cross-account) | Azure Backup (policies, vaults, GRS default, soft delete, immutable vaults; Site Recovery for DR) | Google snapshot schedules (retention mandatory in console and gcloud) and Backup and DR (WORM vaults) | Oracle block volume policies (Bronze, Silver, Gold; cross-region copy on user-defined policies; manual backups to keep forever).
- Incremental: small and fast, but restore needs the chain. Keep fresh full backups.
- Retention: recent points dense, old points coarse. Decide how far back you would really need.
- Protect: separate account or vault, different administrators, immutability, separate keys.
- Test: restore into a new place, compare checksums or a known query, time it, document it, twice a year.
← First Boot on Every Cloud: cloud-init and User Data · ↑ All tutorials · Cloud Security Baseline: A Checklist You Can Audit →