Skip to content

Scheduled Backups

Muppy can run database backups on a schedule.

Backup Tasks

All PostgreSQL backup, restore and copy operations run as Muppy Tasks defined in the script odoo.addons.muppy_postgresql_base.scripts.pg_dump, listed under Muppy / Tasks / Scripts.

Two of them are the ones you schedule:

  • mpy_pg_backup — back up the databases of a cluster.
  • mpy_pg_copy_database — copy databases between clusters.

A third Task, mpy_pg_backup_single_db, backs up one database. You rarely run it directly: mpy_pg_backup runs it for you.

How mpy_pg_backup dispatches the work

mpy_pg_backup selects the databases to back up (from db_names / excluded_db_names), then dispatches:

  • One database — runs inline.
  • Several databases, run as a job — spawns one independent mpy_pg_backup_single_db child task per database. They run in parallel, and each one is followed and can be relaunched on its own.
  • Several databases, run synchronously — loops over them in the parent task.

So a scheduled backup of a ten-database cluster produces one parent message and ten children. Follow them under Muppy / Qs, from the parent.

Setting up a scheduled backup

The steps are the same as for any scheduled Task:

  1. Create a Task Run (Muppy / Tasks / Task Run).
  2. Select the Task — mpy_pg_backup or mpy_pg_copy_database.
  3. Select the Host running the PostgreSQL cluster that holds the databases.
  4. Click Refresh Parameters to list the parameters to fill in.

The Task Run should look like this:

A Task Run for mpy_pg_backup

  1. Fill in the parameters. Each Task parameter form shows its own description.

Task parameter form

  1. Test the configuration with Launch as Job.
  2. Click Create Cron, then open the CRON from the link at the top right of the Task Run.
  3. Configure the CRON.

Scheduled Action (CRON) of a Task Run

Two fields matter (circled in red above):

  • Execute Every — the recurrence interval.
  • Next Execution Date — when the next run happens. Later runs are scheduled by adding Execute Every to it.

Don't untick Active

To stop a scheduled Task, use the Remove Cron button on the Task Run rather than the CRON's Active flag.

mpy_pg_copy_database is set up the same way. Only the parameters differ.

Avoiding a catch-up burst: the execution debounce

When the IMQ worker has been down, every queued parent replays its whole fan-out on return. On 2026-08-09 thirteen stale parents drained in one day and produced around 350 dumps where 24 were wanted.

The execution debounce stops that. Enable it with the dedup_backup_from_cron parameter on mpy_pg_backup: a database is then skipped if it already has a backup younger than half its PG Dump Max Age.

It is a debounce, not deduplication

Nothing is deduplicated. Every message is still enqueued and still consumed — it just returns without dumping. Refusing to enqueue a message while an equivalent one is queued would be deduplication; that is a different mechanism and it is not built. The parameter name predates the distinction.

It measures the artifact, not the message history, so it stays correct after a queue purge, a lost message or a reinstalled worker.

The threshold is half the ceiling on purpose: it sits far below a daily cadence, so it never fires in normal operation, and it can never push a database past the PG Dump Max Age its own monitoring alerts on.

It is opt-in, per Task Run

dedup_backup_from_cron defaults to False, so every backup launched by hand — the wizards, a database's Backup button, the backup taken before a deploy — always dumps. A backup produces: a skipped run is a recovery point that does not exist.

Set it to True on the Task Run bound to the backup cron, and nowhere else.

PG Dump Max Age is set per database, on its Monitoring tab — see Backup Monitoring.