23.9. Backups
Table of Contents
Why Backups Matter in Backend Systems
Backups are your safety net. No matter how well you design and secure your backend, things will eventually go wrong: disks fail, developers run the wrong script, a migration goes bad, or data gets corrupted.
A backup is a copy of your data, configuration, or system state that you can restore later if you lose or damage the original.
A backend with no reliable backups is a backend that is guaranteed to lose data sooner or later.
For production backends, you should treat backups as a core part of deployment, not as an optional extra.
Common situations where backups save you:
- Hardware failure on the database server
- Accidental
DELETEorDROP TABLE - Buggy deployment or migration corrupts data
- Ransomware or malicious deletion
- Cloud region outage or account problems
Your goal is not only to create backups, but to ensure you can restore from them quickly, reliably, and to the right point in time.
What You Need to Back Up
In a typical backend deployment you usually care about more than just the database.
Core backup targets
| Target | Why it matters |
|---|---|
| Database (PostgreSQL, etc.) | Main source of truth for business data |
| Object storage (S3, etc.) | User uploads, reports, exported files |
| Configuration & secrets | How the app runs, connects, and authenticates |
| Application data that is not in DB | Caches you want to persist, job queues (sometimes) |
| Infrastructure config (IaC, scripts) | How to rebuild the environment |
You normally do not need to back up:
- Docker images (can be rebuilt from Dockerfiles)
- Application source code (already in Git)
- Ephemeral caches (Redis used as cache only)
Focus on data that is unique and cannot be recreated.
Types of Backups
There are a few common backup types. Choosing between them is a tradeoff between storage cost, backup time, and restore time.
Full, incremental, and differential backups
| Type | What it stores | Pros | Cons |
|---|---|---|---|
| Full | Complete copy of all data | Simple, fastest restore | Large, slow to create, costly storage |
| Incremental | Changes since the last backup of any type | Small, fast to create, saves space | Restore can require many backup files |
| Differential | Changes since the last full backup | Faster restore than incremental | Grows larger until next full backup |
Typical approach:
- Daily incremental backups
- Weekly full backups
This balance keeps restore steps manageable and storage costs reasonable.
Logical vs physical backups (databases)
For databases like PostgreSQL there are two conceptual approaches.
Logical backups
Export SQL or data representation:
- PostgreSQL example:
pg_dumpandpg_restore - Often produce
.sqlor custom dump formats
Pros:
- Can restore to different versions or servers
- Human-inspectable (to some degree)
- Good for schema and data migrations
Cons:
- Slower for very large databases
- Restores can take a long time
Physical backups
Copy the actual database files or use filesystem-level snapshots or tools like pg_basebackup.
Pros:
- Faster for large databases
- Better for full cluster recovery
- Supports point-in-time recovery together with WAL logs
Cons:
- Tied to engine version and configuration
- Harder to inspect
- Usually more complex to set up correctly
In small to medium projects, logical backups are often enough. As your database grows, you will likely combine physical backups with WAL archiving or cloud-native backups.
Backup Strategy: RPO and RTO
Before picking tools, define how much data loss is acceptable and how quickly you must recover.
RPO: Recovery Point Objective
RPO is the maximum acceptable amount of data you can afford to lose, usually measured in time.
Examples:
- RPO = 24 hours: Losing 1 day of data is acceptable
- RPO = 5 minutes: You can only lose a few minutes of data
RPO tells you how often you must back up or replicate data.
RTO: Recovery Time Objective
RTO is the maximum acceptable time your system can be down before being restored.
Examples:
- RTO = 4 hours: You can be offline for up to 4 hours
- RTO = 5 minutes: You need very fast failover or restore
RTO tells you how fast your recovery process must be.
Design your backup and restore process to satisfy both RPO and RTO. A backup that takes 24 hours to restore is useless if your RTO is 1 hour.
The 3-2-1 Backup Rule
A classic and very practical rule for production backups is the 3-2-1 rule:
3-2-1 rule
- Keep 3 copies of your data
- On 2 different types of storage
- With 1 copy offsite
Concretely, for a hosted backend:
- Copy 1: Production database itself
- Copy 2: Automatic database snapshot in the same cloud region
- Copy 3: Encrypted backup stored in another region or another provider
Storage types might differ by:
- Block storage vs object storage
- Different cloud providers
- On-premises vs cloud
The goal is to avoid losing all copies due to a single incident such as region failure or provider issue.
Database Backups in Practice
Most backends depend heavily on a relational database. Here is how to think about backing it up in a real deployment.
Scheduling database backups
At minimum:
- Nightly full logical dump (for small to medium databases)
- Frequent incrementals or WAL archiving if you need lower RPO
Examples of schedules:
| Scenario | Full backup | Incremental / logs |
|---|---|---|
| Small hobby project | Daily full | None |
| Small production app | Daily full | WAL or hourly incremental |
| High-traffic production system | Weekly full | Continuous WAL archiving |
Example: PostgreSQL logical backup
A simple script on a Linux server:
#!/usr/bin/env bash
set -e
# Configuration
DB_NAME="myapp"
DB_USER="backup_user"
BACKUP_DIR="/var/backups/postgres"
DATE=$(date +"%Y-%m-%d_%H-%M")
FILE="$BACKUP_DIR/${DB_NAME}_${DATE}.dump"
mkdir -p "$BACKUP_DIR"
pg_dump \
--format=custom \
--file="$FILE" \
--username="$DB_USER" \
"$DB_NAME"
# Optional: compress further or upload to object storage
gzip "$FILE"
Then schedule with cron:
0 3 * * * /usr/local/bin/backup_postgres.sh >> /var/log/backup_postgres.log 2>&1This creates one compressed backup per night at 03:00.
Testing database restore
A backup is only useful if you can restore it. Always test the full process.
Example for PostgreSQL:
createdb restore_test
pg_restore --dbname=restore_test --clean /path/to/backup.dumpCheck:
- Can you connect to
restore_test? - Are tables and data present?
- Does the schema look correct?
Make this test part of a regular operations checklist.
Application and Configuration Backups
Even if your application code is in Git, your running system includes more:
- Environment configuration
- Secrets
- Infrastructure definitions
Configuration
Configuration often comes from:
.envfiles- Kubernetes manifests or Helm charts
- Terraform or other IaC files
- Nginx or reverse proxy configs
Best practice:
- Store configuration as code in Git
- Encrypt sensitive parts when appropriate (for example using a secret manager or Git crypt)
- Back up the Git repository through your Git hosting provider or separate mirrors
Secrets
Secrets include:
- Database passwords
- API tokens
- Encryption keys
- JWT signing keys
Do not store secrets unencrypted in backups.
Typical approach:
- Use a secret manager (AWS Secrets Manager, HashiCorp Vault, etc.)
- Back up the secret manager itself or rely on provider’s durability
- For self-hosted Vault, back up its storage backend and unseal keys securely
If you must include secrets in backups:
- Encrypt the backup file with strong encryption (for example
gpgor provider-managed key encryption) - Store encryption keys separately from the backups
File and Object Storage Backups
User-uploaded files and generated assets are often stored in:
- Local filesystem on the server
- Network storage
- Object storage like S3 or compatible services
Local filesystem backups
If your uploads live on the server disk (for example /var/www/uploads):
- Use tools like
rsync,tar, orborgbackupto copy to another disk or to remote storage - Schedule backups with
cron - Consider using snapshots if your disk supports it (for example LVM or ZFS)
Typical script with tar:
#!/usr/bin/env bash
set -e
SRC="/var/www/uploads"
DEST="/backups/uploads_$(date +'%Y-%m-%d').tar.gz"
tar -czf "$DEST" "$SRC"Object storage backups
S3 and compatible services are durable, but you may still want:
- Versioning, to recover from accidental overwrite
- Replication to another region
- Backups to another provider
Useful strategies:
- Enable bucket versioning for critical buckets
- Enable cross-region replication
- Periodically sync to another provider using tools like
rcloneoraws s3 sync
Example with AWS CLI:
aws s3 sync s3://myapp-uploads s3://myapp-uploads-backup --storage-class STANDARD_IABackup Storage: Where to Keep Backups
Choosing backup storage affects cost, durability, and security.
Options
| Storage type | Pros | Cons |
|---|---|---|
| Same server disk | Fast, simple | Lost if server fails |
| Separate disk on same server | Handles disk failure | Not safe against server loss |
| Network-attached storage | Can be resilient, shared | Complexity, cost |
| Cloud object storage (S3, etc.) | Durable, cheap at scale | Requires careful security |
| Another cloud/provider | Protects against provider-wide issues | More complexity |
| Offline storage (cold backups) | Protects against online attacks | Hard to automate, slow restore |
A common practical pattern:
- Write backup to a local temporary file
- Upload it to object storage in the same cloud
- Replicate or sync to another region or provider
Backup Retention Policies
You do not want to keep every backup forever.
A retention policy defines how long you keep each backup.
Example policy:
- Keep daily backups for 7 days
- Keep weekly backups for 4 weeks
- Keep monthly backups for 12 months
This is sometimes called a backup rotation scheme.
You can implement retention:
- In your backup script, deleting old files after upload
- Using lifecycle rules in object storage (for example S3 Lifecycle)
Example with S3 lifecycle:
- Rule 1: Delete objects with prefix
daily/after 7 days - Rule 2: Delete objects with prefix
weekly/after 30 days
Make sure your retention supports:
- Compliance or legal requirements, if any
- Your need to debug old issues
Security of Backups
Backups often contain everything. If someone gains access to your backup, they may get:
- All user data
- All secrets and passwords
- All business information
So backups need at least as much protection as production data, often more.
Encrypt backups
Encrypt backups at rest:
- Use provider-managed encryption (for example S3 SSE-KMS)
- Or encrypt manually using tools such as
gpgoropenssl
Example using gpg:
tar -czf db_backup.tar.gz db_backup.dump
gpg --encrypt --recipient backup@mycompany.com db_backup.tar.gzKeep private keys in a secure place (for example a hardware token or secret manager).
Restrict access
Follow least privilege:
- Only specific backup or ops accounts can read/write backups
- Disallow public access to backup buckets
- Log access and periodically review
Protect against ransomware and malicious deletion
Consider:
- Immutable backups (write-once, read-many) for a certain period
- Separate accounts for backup storage, with minimal write permissions from production
Some object storage services support object lock or worm mode to prevent deletion before a set time.
Automating and Monitoring Backups
Manual backups will be forgotten. Production backups must be:
- Automated
- Monitored
- Reported
Automation
Use:
- Cron jobs on servers
- CI/CD pipelines for some backup tasks
- Managed backup features from your database or cloud provider
Example cron entry for a nightly backup:
0 2 * * * /usr/local/bin/backup_database.shMonitoring
You should know immediately when backups fail.
Typical monitoring:
- Backup script exits with non-zero status on failure
- Logs go to central logging system
- Alert if:
- No backup file appears in the expected location
- Backup size is suspiciously small or large
- Backup job fails or exceeds time limit
You can integrate with:
- Prometheus metrics and alerts
- Hosted monitoring services
- Email or Slack notifications from backup scripts
Disaster Recovery and Restore Procedures
Backups are only half of the story. Disaster recovery is the full plan to bring your system back.
Define recovery procedures
Document step by step:
- Where to find the latest valid backup
- How to provision or choose a target server or database
- How to restore:
- Database
- Files or object storage
- Configuration and secrets
- How to verify the restored system
- How to point traffic (DNS, load balancer) to the restored system
Example: Database disaster recovery checklist
- Spin up a new database instance
- Download the latest backup from object storage
- Restore with
pg_restoreor equivalent - Apply any necessary schema migrations that are not in the backup
- Update application configuration to point to new database
- Run smoke tests or health checks
- Enable traffic
Practice disaster recovery
Do regular drills:
- Quarterly or at set intervals
- Use backups to restore to a staging environment
- Measure:
- Actual RTO (how long it took)
- Whether RPO requirements were met
This also helps you discover:
- Missing documentation
- Broken backup scripts
- Privilege or access issues
Backups in Containerized and Cloud-native Environments
With Docker and orchestrators like Kubernetes, the running containers are usually ephemeral. Backups focus on persisted data.
Docker and volumes
When using Docker:
- Do not store critical data inside the container’s filesystem
- Use volumes or bind mounts
- Back up the volume content on the host or via volume plugins
Example pattern:
- PostgreSQL data lives in a Docker volume
pgdata - On the host,
pgdatais mapped to/var/lib/docker/volumes/pgdata/_data - Backup script reads from that host path or uses
pg_dumpfrom a container that can access the database
Kubernetes and cloud services
For Kubernetes:
- PersistentVolumes are backed by cloud disks
- Use:
- Database-as-a-Service with built-in backups (for example RDS, Cloud SQL)
- Or tools like Velero to back up PersistentVolumes and cluster state
For cloud-managed databases and object storage:
- Use the provider’s automatic backup and snapshot features
- Understand:
- Retention periods
- Point-in-time restore capabilities
- Region replication options
Cloud-native backups do not remove the need for testing restores.
Integrating Backups into Your Deployment Process
Since this chapter sits in the Deployment section, tie backups into how you ship and run your app:
- When you deploy a schema migration, ensure you have:
- A recent database backup
- A rollback plan if the migration fails
- When you change infrastructure (for example disk, database instance type), confirm backup and restore steps for the new setup
- When you scale to new regions, design region-specific backups
A simple rule for deployments that touch data:
Never apply irreversible database changes in production without a recent, tested backup and a clear restoration plan.
Even for smaller projects, a minimal practice is:
- Nightly database backup
- Weekly restore test to a separate environment
- Version-controlled infrastructure and configuration
This discipline makes your backend significantly more resilient and trustworthy.
Views: 6
KAHIBARO