Automate Database and Media Backups With django-dbbackup

Use django-dbbackup to back up the Django database and media to S3 or other storage on a schedule: configuration, compression and GPG encryption, cleanup, restores with dbrestore and mediarestore, and its limits compared with native tools.

Problem statement

Many Django projects launch without automated backups, or with a shell script someone wrote once and nobody monitors. django-dbbackup adds management commands that dump the database and archive media files to any Django storage backend (local disk, S3, R2, SFTP), with optional compression, encryption, and cleanup of old backups. Run on a schedule with monitoring, it gives a small team reliable, off-site backups that restore with a single command, as long as you understand where it fits next to native tools and managed backups.

Backups with django-dbbackupdbbackuppg_dump under the hoodmediabackuptar of MEDIA_ROOTStorage backendS3, encryptedScheduled + testedtimer, heartbeatThe commands wrap native dump tools and ship results to off-site storage you configure.
  1. pip install django-dbbackup and add dbbackup to INSTALLED_APPS.
  2. Configure STORAGES["dbbackup"] (Django 4.2+) or DBBACKUP_STORAGE to point at a private S3 bucket or other off-site storage.
  3. Schedule python manage.py dbbackup --clean --compress (and mediabackup if media is on disk) daily with a timer, Beat, or a CronJob.
  4. Encrypt with --encrypt and a GPG recipient, or rely on bucket encryption plus strict access.
  5. Keep retention with --clean and DBBACKUP_CLEANUP_KEEP, plus bucket lifecycle rules.
  6. Test restores regularly with dbrestore into a scratch database, and add heartbeat monitoring.

Step-by-step solution

1. Install and configure storage

INSTALLED_APPS += ["dbbackup"]

STORAGES = {
    "default": {"BACKEND": "storages.backends.s3.S3Storage", "OPTIONS": {"bucket_name": "myapp-media"}},
    "staticfiles": {"BACKEND": "whitenoise.storage.CompressedManifestStaticFilesStorage"},
    "dbbackup": {
        "BACKEND": "storages.backends.s3.S3Storage",
        "OPTIONS": {"bucket_name": "myapp-backups", "location": "db", "default_acl": "private"},
    },
}
DBBACKUP_CLEANUP_KEEP = 14
DBBACKUP_CLEANUP_KEEP_MEDIA = 7

Use a separate bucket from media, in another region or account if possible, with credentials that can write backups but ideally not delete them (deletion handled by lifecycle rules).

2. Take backups

python manage.py dbbackup --compress --clean
python manage.py mediabackup --compress --clean      # only if media lives on local disk
python manage.py listbackups

For PostgreSQL, dbbackup runs pg_dump with your Django connection settings, so the PostgreSQL client tools must be installed in the image or server, at a version at least as new as the server.

backup options for a Django appRestore granularityBest fordjango-dbbackupper backup run✓small teams, simple setuppg_dump scriptper backup runcustom pipelinesManaged DB backupsdaily + PITR✓managed PostgresWAL archiving (PITR)✓any secondlow data-loss toleranceDaily dumps lose up to a day of data; PITR narrows that to secondsdjango-deployment.com
Use django-dbbackup as an extra off-site copy even with managed backups.

3. Encrypt

python manage.py dbbackup --compress --encrypt

with DBBACKUP_GPG_RECIPIENT = "backups@example.com" and the public key imported on the server (python-gnupg installed). Keep the private key offline or in a secrets manager; without it, encrypted backups cannot be restored. Bucket-side encryption (SSE-S3 or KMS) protects at rest but not against someone with bucket read access.

4. Schedule and monitor

# /etc/systemd/system/dbbackup.service
[Service]
Type=oneshot
User=deploy
WorkingDirectory=/srv/app/current
EnvironmentFile=/etc/myapp/env
ExecStart=/srv/app/current/.venv/bin/python manage.py dbbackup --compress --encrypt --clean
ExecStartPost=/usr/bin/curl -fsS -m 5 https://hc-ping.com/<uuid>
# dbbackup.timer
[Timer]
OnCalendar=*-*-* 02:30:00
Persistent=true

A heartbeat check alerts if a night's backup does not run.

5. Restore

python manage.py dbrestore --decrypt --uncompress --database default          # latest backup
python manage.py dbrestore -i default-2026-10-02-023000.psql.gz.gpg --decrypt --uncompress
python manage.py mediarestore --uncompress

Practise on a scratch database first (point settings at it with an environment variable), then compare row counts and log in. Restoring over production overwrites data; take a fresh backup before doing it.

backups you can restoreSeparate private backup bucketother region or accountClient tools match the server versionpg_dump in the imageEncrypted, key stored safelyGPG or KMSScheduled with a heartbeatalert on a missed nightRestore tested monthlyinto a scratch databaseAn untested backup is a hope, not a recovery plandjango-deployment.com
Time the restore test so you know how long recovery takes.

Verification check: listbackups shows a new backup each day in the bucket, old ones are pruned, a monthly restore into a scratch database succeeds with matching row counts, and the heartbeat dashboard is green.

Explanation

django-dbbackup is a thin, Django-aware wrapper: it reads database settings to call the right dump tool (pg_dump, mysqldump, or SQLite file copy), streams the result through optional compression and GPG encryption, and writes it to a Django storage backend, which makes off-site storage a settings change. Media backups archive MEDIA_ROOT. Its value is convenience and consistency for small teams; it does not provide continuous point-in-time recovery, so data written between backups can be lost.

Edge cases / notes

  • Large databases make single dumps slow; consider native tools with parallel jobs or managed snapshots.
  • Media on S3 does not need mediabackup; use bucket versioning and replication instead.
  • Docker images need postgresql-client installed for pg_dump.
  • Consistency between database and media backups is not atomic; back up the database first, then media.

Next steps

FAQ

What does django-dbbackup do?

It provides management commands to back up and restore the database and media files to Django storage backends.

Does django-dbbackup replace managed database backups?

No. Use it as an additional off-site copy; managed services add point-in-time recovery.

Why does dbbackup fail with pg_dump errors?

The PostgreSQL client tools are missing or older than the server. Install a matching pg_dump.

How do I restore a django-dbbackup backup?

Run python manage.py dbrestore (with --decrypt and --uncompress if used), ideally into a scratch database first.

Keep going