Backups, and what to do when something falls over
What has to be saved
Section titled “What has to be saved”Three things, and only the first is unrecoverable:
| What | Where | If you lose it |
|---|---|---|
| The database | Postgres | You have lost everything: orders, customers, products |
| Uploaded images | the backend’s static/ |
Product pages with no photos, and they do not regenerate |
| Cache and queues | Redis | Nothing. It rebuilds itself |
Under Docker these are the db, static and redis volumes.
Backing up the database
Section titled “Backing up the database”pg_dump -Fc "$DATABASE_URL" > store-$(date +%F).dumpCompressed format (-Fc) because it lets you restore individual parts.
Put it in a daily cron and keep it off the server. A copy on the same machine does not protect against the case that happens most: losing the machine.
Restoring:
pg_restore --clean --no-owner -d "$DATABASE_URL" store-2026-08-04.dumpBefore every migration
Section titled “Before every migration”Any update that touches the database deserves a backup right before, even if you have the daily one. The daily one is from this morning; the migration is from now.
pg_dump -Fc "$DATABASE_URL" > pre-migration-$(date +%F-%H%M).dumpnpm run preparar # applies whatever the schema is missing and prepares the shoppreparar takes a lock in Postgres: two servers starting at once do not step
on each other applying the same migration. And it deletes nothing: if something
fails, the database stays as it was and the backup is still there just in case.
Images live outside the code
Section titled “Images live outside the code”Photos uploaded from the panel go to the static/ folder, which in the
container is a separate volume. On purpose: if they lived next to the code,
every update would wipe them. When you back up, back up that volume too — the
database stores the URLs, not the images.
Watching that it is still up
Section titled “Watching that it is still up”A backend that falls over at 4am does not report itself. A checker every few minutes that looks at whether the store responds and restarts it if not costs ten lines and saves the customer’s phone call asking why their site has been erroring for hours.
Two things that help if you use pm2:
- Growing wait between restarts. If the database restarts — the system’s automatic updates do it overnight — the backend goes down and, without a wait, relaunches in a loop dozens of times per incident.
- Log rotation, or the file grows without limit until it fills the disk.
What almost nobody checks until it hurts
Section titled “What almost nobody checks until it hurts”- Does the backup actually restore? A backup that has never been tested is not a backup, it is a file.
- Is it off the server?
- How much data are you willing to lose? That decides whether the backup is daily or hourly.