Django Backup and Recovery Checklist
Check that Django backups actually protect you: what to back up, schedules, off-site copies, encryption, retention, restore drills, and monitoring.
Problem statement
Backups fail quietly. A cron job stops running after a server rebuild, a dump completes but contains an empty database because credentials changed, an S3 bucket lifecycle rule deletes the only copies after 30 days, or the encryption passphrase lives only in the memory of someone who left. None of this is visible until a restore is needed, which is the worst moment to discover it.
This checklist reviews a Django project's backup and recovery setup end to end: what is backed up, how often, where copies live, who can reach them, how restores are tested, and how failures are detected. It covers self-managed PostgreSQL and managed databases, media files, and the configuration needed to rebuild an environment.
Quick answer
- Inventory everything needed to rebuild: database, media, configuration and secrets, infrastructure definitions, and DNS records.
- Match backup frequency to your acceptable data loss (RPO): nightly dumps for a 24-hour RPO, continuous archiving or managed point-in-time recovery for minutes.
- Store copies off the server and outside the production account, encrypted, with retention that covers late-discovered problems.
- Restrict who and what can delete backups; application credentials must not be able to.
- Monitor every backup job with heartbeats and verify backup contents, not just job exit codes.
- Test restores on a schedule and measure how long a full restore takes.
- Document the restore procedure so someone else can follow it.
Checklist
1. Inventory: what must be recoverable
| Item | Typical approach | Notes |
|---|---|---|
| Database | pg_dump and/or continuous archiving, or managed backups | the core data |
| Media and uploads | object storage versioning plus copies, or restic snapshots | often the largest volume |
| Secrets and configuration | secret manager with its own backup, or encrypted export | needed to start the app |
| Infrastructure definitions | Git repository (Terraform, Ansible, Compose files) | needed to rebuild servers |
| Application code and images | Git remote and container registry | verify they are not only on one machine |
| DNS records | exported zone file or infrastructure code | needed for cutover |
Anything not on this list must be reproducible from what is, or it is a gap.
2. Database backup method matches the RPO
- Nightly logical dumps: simple and portable; RPO up to 24 hours.
pg_dump --format=custom --compress=6 --file="/var/backups/myapp-$(date +%F).dump" "$DATABASE_URL"
- Continuous archiving (PITR): base backups plus WAL, with tools such as pgBackRest or WAL-G; RPO of minutes, restore to any point in time.
- Managed service backups: automated daily snapshots plus transaction log retention; check the retention window and that PITR is enabled.
Verify the method in use answers your RPO, and that the dump uses a role able to read all required data.
3. Schedule and automation
What to check:
systemctl list-timers | grep -i backup
sudo crontab -l | grep -i backup
Guidelines:
- Backups run automatically, not manually.
- Media backups run after database backups, so files referenced by the database exist.
- Jobs use
set -euo pipefail(or equivalent) so a failing step does not produce a truncated backup that looks successful. - Long-running backups do not overlap; use systemd timers (which skip while active) or
flock.
4. Off-site and off-account copies
Guidelines:
- Copies exist outside the application server.
- At least one copy is in a different cloud account, provider, or region.
- Backup storage credentials are separate from application credentials.
- Application and server credentials cannot delete backups (append-only or write-only access, object lock, or versioning without delete permission).
- Restore credentials are documented and accessible during an incident, including if the production account is unavailable.
5. Encryption
Guidelines:
- Backups encrypted at rest (restic encrypts by default;
pg_dumpoutput needs encryption applied, for example withageor provider-side encryption). - Encryption keys or passphrases stored in a password manager separate from the backups themselves, with at least two people able to retrieve them.
- Transfers over TLS.
6. Retention
Guidelines:
- Retention covers problems discovered late (a corrupted record noticed weeks later), for example 14 daily, 8 weekly, and 12 monthly copies.
- Retention policy applied automatically (
restic forget --prune, lifecycle rules, or provider settings), not by manual deletion. - Legal or contractual retention requirements met, and personal data deletion obligations considered: backups containing deleted user data need a documented policy.
7. Monitoring and verification
Job success is not enough; verify the artifact:
# Verify a PostgreSQL custom-format dump is readable and non-trivial
pg_restore --list /var/backups/myapp-$(date +%F).dump | head -5
ls -lh /var/backups/myapp-$(date +%F).dump
Guidelines:
- Heartbeat monitoring for every backup job, alerting when a run is missing.
- Alert on unusually small backups (for example less than 80 percent of the previous size), which can indicate partial dumps.
restic checkor equivalent integrity checks on a schedule.- Backup metrics visible on a dashboard: last successful run, size trend, restore test date.
8. Restore procedures documented
For each backup type, a written procedure with commands:
# Restore a dump into a scratch database
createdb myapp_restore_test
pg_restore --dbname=myapp_restore_test --no-owner --jobs=4 /var/backups/myapp-2026-09-16.dump
psql -d myapp_restore_test -c "SELECT count(*) FROM auth_user;"
Include: where backups live, how to get credentials, expected duration, verification queries, and how to point the application at restored data.
9. Restore testing schedule
| Test | Frequency | What it proves |
|---|---|---|
| Automated restore of the latest dump into a scratch database with row count checks | weekly or nightly | backups are readable and non-empty |
| Restore database and media into staging; run the app against them | quarterly | the full dataset works with the application |
| Full environment rebuild from infrastructure code plus backups | yearly | the recovery path works without the original servers |
Record the date and duration of each test. A backup system without a recent successful restore is an assumption.
10. Point-in-time recovery drill
If you rely on PITR, practice restoring to a specific timestamp, because the procedure differs from restoring a plain dump:
- Choose a target time (for example five minutes before a simulated bad migration).
- Restore a base backup and replay WAL to that time, or use the managed service's PITR feature.
- Verify data reflects the target time.
- Record the total time taken.
11. Special data considerations
- Sessions and caches: usually not worth backing up; they regenerate.
- Search indexes: rebuildable from the database; document the rebuild time.
- Generated files (thumbnails, exports): decide whether to back up or regenerate.
- Personal data: restores may reintroduce data a user asked to delete; have a process for re-applying deletions after a restore.
Verify
Verification check:
- every item in the inventory has a backup method and a documented restore path
- backups are stored off-server, in another account or region, and encrypted
- application credentials cannot delete backups
- a restore test succeeded recently, with the date recorded
- monitoring alerts when a backup job does not run or produces an unusually small artifact
- at least two people can access backup storage and encryption keys
Explanation
A backup system is a chain: data selection, scheduling, transfer, storage, retention, access control, and restore. A break anywhere makes the whole chain useless, and most breaks are silent. Regular restore tests exercise the entire chain and are the only reliable evidence that recovery works, which is why they belong on a schedule rather than in the plan for the next incident.
Edge cases / notes
Managed database backups
Providers handle scheduling and storage, but retention windows are limited and backups usually live in the same account. Export periodic copies elsewhere if account-level loss is in your threat model.
Very large databases
Restore time grows with size and can exceed your RTO even when backups are perfect. Measure it, and consider replicas or faster restore methods if the measured time is too long.
Encryption key loss
An encrypted backup without its key is not a backup. Store keys with the same care as the backups, in a separate location, with documented recovery access.
Common mistakes
- Backing up the database but not media or configuration.
- Keeping the only copies on the production server or in the production account.
- Monitoring job exit codes but never checking backup contents.
- Never restoring, or restoring only in the same environment that created the backup.
Next steps
- Implement database backups with Backup and Restore PostgreSQL for Django Apps.
- Cover uploads with Back Up Django Media Files.
- Put it all in context with Write a Disaster Recovery Plan for a Django App.
- Review database operations with the PostgreSQL Production Checklist for Django.
FAQ
What should a Django backup include besides the database?
User uploads, configuration and secrets, infrastructure definitions, DNS records, and anything else required to rebuild the environment from nothing.
How often should Django database backups run?
Frequently enough to meet your acceptable data loss. Nightly dumps allow up to a day of loss; continuous archiving or managed point-in-time recovery reduces that to minutes.
How do I know my backups are usable?
Restore them. Automate a weekly restore into a scratch database with validation queries, and run fuller restore drills into staging quarterly.
Should application servers be able to delete backups?
No. Use separate credentials with append-only or write-only access, and enable versioning or object lock so a compromised application cannot destroy recovery data.