Most self-managed VPS backup failures have the same root cause: the backup runs on the same disk it is meant to protect, or it is retained for a period nobody ever chose deliberately. A backup strategy is really two decisions — where the copy lives, and how many copies you keep — and both have a measurable monthly cost. This article works through the storage maths for a single small server, compares four backup methods on cost per recovery point, and gives a schedule that fits under $3 per month for most sites.
The three failure modes any backup plan must cover
- File-level mistakes — a bad deploy deletes a directory, a plugin overwrites a config. Needs a copy within hours, recoverable without touching the whole server.
- Data corruption — a database write goes wrong and is only noticed days later. Needs retention long enough to reach a copy from before the corruption started; seven to fourteen days is the practical minimum.
- Total node loss — the provider’s disk fails or the account is terminated. Needs a copy that does not live on the provider at all.
A snapshot taken by the provider covers only the third case, and only if it is stored separately from the node. An in-place rsync to another directory covers none of them. Most budget backup setups fail because they were designed for one failure mode and assumed it covered the rest.
How much data you are actually protecting
Measure before you choose a storage class. The relevant figure is not total disk usage but compressible application data:
# application + config data, excluding logs and caches
du -sh /var/www /etc /var/lib/mysql 2>/dev/null
# compressed size, the number that matters for storage cost
tar -C / -czf - var/www etc 2>/dev/null | wc -c | awk '{print $1/1048576 " MB"}'
A typical small WordPress site compresses to 200–600 MB, a Next.js or Django app with uploads to 1–3 GB, and a database-only workload to under 100 MB. Logs and node_modules can be most of the disk and none of the value — exclude them and the backup shrinks by an order of magnitude.
Four methods, costed per recovery point
| Method | Storage cost | Effort | RPO | Covers corruption? | Offsite? |
|---|---|---|---|---|---|
| Provider snapshot add-on | $1–$5/mo flat | Very low | Daily | Only if retention > 7 days | Usually yes (same provider) |
| Borg to object storage | ~$1.20/mo per 100 GB-month* | Medium | Hourly possible | Yes, deduplicated versions | Yes |
| rsync / restic to second VPS | $3–$5/mo for the server | Medium | Hourly | Yes if versioned | Yes |
| Local tarball on same disk | $0 | Low | Daily | No | No |
*Illustrative rate of $0.012/GB-month with compression and deduplication applied to the 200–600 MB figures above.
The interesting result is that offsite object storage is not the expensive option. For a 500 MB site with 14 daily versions, deduplication typically stores 1.5–2.5 GB total, which lands under $0.05 per month at object-storage rates — far below the $1–$5 a provider charges for snapshot add-ons. What you pay for with a snapshot add-on is convenience, not capacity.
A schedule that fits the budget
Three tiers, each cheap enough to keep all three:
# 1. Database dump every 6 hours, keep 7 days
0 */6 * * * mysqldump --single-transaction app | gzip > /var/backups/db-$(date +\%H).sql.gz
# 2. Application files to Borg repo, nightly, keep 14 daily + 8 weekly
30 2 * * * borg create --compression zstd,6 ssh://bk@backup-host/./repo::app-{now:%Y%m%d} /var/www /etc/nginx
# 3. Offsite copy to object storage, weekly, immutable
0 4 * * 0 restic backup --files-from /etc/restic/include --tag weekly
Run the pre-backup step of your database engine’s own dump utility rather than tarring live data files — a tarred MySQL data directory restored from a running server is frequently inconsistent. For Postgres, pg_dump or a filesystem snapshot taken with the database quiesced.
Monthly cost of protecting a small server
| Item | Monthly | Notes |
|---|---|---|
| Object storage, 3 GB stored | $0.04 | After dedupe and compression |
| Egress to verify a restore | $0.01–$0.10 | Only when you actually restore |
| Convenience snapshot add-on (optional) | $1–$5 | Buy for speed, not coverage |
| Second small VPS for rsync target (optional) | $3–$5 | Only if you want a hot standby |
| Recommended minimum total | <$1 | Database dumps + Borg + offsite weekly |
Under a dollar per month for a strategy that survives all three failure modes is the best value line item on a budget server. The constraint is not money; it is whether anyone has tested a restore.
Verify with an actual restore, quarterly
A backup that has never been restored is a hypothesis. Once a quarter, take the newest archive to a throwaway instance, unpack it, start the service, and check one real page and one real query. Do it on an hourly-billed server so the test costs cents. Record the time it takes from “start” to “serving traffic” — that number, not the backup size, is your real recovery time objective.
- Restore the database dump first and confirm row counts.
- Restore files and check file ownership and permissions — the most common restore breakage.
- Confirm TLS certificates are covered; forgetting
/etc/letsencryptstalls a restore for ten minutes. - Record the restore duration in your runbook.
When the backup needs more budget
Two cases justify spending more. First, large upload volumes: above about 50 GB, incremental backups and a storage tier with cheap retrieval matter more than provider convenience, and bandwidth to move the data can become the real cost. Second, compliance or client contracts requiring immutable, encrypted, geographically separate copies — that rules out snapshots on the same provider. For the typical budget site, neither applies, and a sub-dollar setup beats a $5 add-on on both cost and actual coverage. If you are choosing a server tier now, the comparison of low-cost VPS plans and their backup options shows which providers bundle snapshots and which charge separately; the budget hosting cost guides cover the wider line-item picture.
