Retention Policy¶
Why Retention Matters¶
Backup files accumulate quickly. A single Odoo instance with a 500 MB database, backed up daily, fills 15 GB per month. Without a retention policy, disk usage grows without bound. The orchestrator's retention system automates cleanup while providing a hard safety guarantee: the last surviving backup is never automatically deleted.
Retention Modes¶
Each job has an independent retention policy. Two modes are available:
Keep Last N (keep_last_n)¶
Keeps the N most recent successful backups for each database. After a successful run, the orchestrator sorts all existing backups for that database by creation time (newest first) and deletes anything beyond position N.
Example: keep_last_n = 7
run-001 2024-03-08 → kept (position 7)
run-002 2024-03-09 → kept (position 6)
...
run-007 2024-03-14 → kept (position 1, newest)
run-008 2024-03-15 → kept (just created)
run-000 2024-03-07 → deleted (position 9 > 7)
Minimum value: 1. Setting keep_last_n = 0 is rejected at the API layer.
Older Than N Days (older_than_days)¶
Deletes backups whose creation timestamp is older than N days from the current time. This mode is useful when you want a rolling window regardless of how many runs fired (e.g., if you added extra manual runs).
Example: older_than_days = 30
At evaluation time (2024-04-15), any backup created before 2024-03-16 is eligible for deletion.
Minimum value: 1. Setting older_than_days = 0 is rejected at the API layer.
The Safety Net¶
Last-backup protection
If the computed deletion set would remove every backup for a given database, the orchestrator skips all deletions for that database and writes a warning to the audit log.
This prevents two dangerous scenarios:
-
Aggressive policy on a rarely-running job — e.g.,
older_than_days = 7on a job that fires weekly. If the weekly run fails for 8 days, there may only be one backup remaining. Without the safety net, the policy would delete it. -
Migration mistake — e.g., accidentally setting
keep_last_n = 1and the most recent run failed. The last successful backup is preserved.
The safety net is silently triggered (no UI error). You will see a log line and an audit entry when it fires. Inspect Audit Log (accessible from the sidebar) to review these events.
Per-Database Scope¶
Retention is scoped per database name, not per job. If your instance backs up three databases (odoo, demo, test), retention runs independently for each. Losing runs for demo does not affect the odoo backup count.
Retention Timing¶
Retention runs after a successful backup, not on a separate schedule. The sequence for each job run is:
- Download backup → save to disk
- Verify archive integrity (if enabled)
- Apply retention (delete old files, respecting safety net)
- Upload to cloud destinations (parallel)
- Send notifications (parallel)
Retention does not run after a failed backup. If a run fails, existing backups are left untouched.
Manual Deletion¶
You can delete individual backups from the Run History table in the UI. Click the trash icon on any run row.
If the backup you're deleting is the last remaining backup for that database, the API requires two extra confirmation parameters:
force=trueconfirmation=DELETE
The UI presents a confirmation dialog that sets these automatically. This guard exists to prevent accidental permanent data loss.
Disk Space Planning¶
Use the following rough formula to estimate disk requirements:
For example: 10 instances × 3 databases × 0.5 GB × 7 days = 105 GB.
Add 20–30% headroom for in-progress backups and temporary files during compression.
Monitor disk usage with the /api/health endpoint (which reports disk_free_gb) or your host's monitoring system. The orchestrator does not yet enforce a minimum free-space threshold before starting a backup.
Remote Retention¶
Cloud sync destinations have their own independent retention setting (keep last N on the binding). See Cloud Sync → Remote Retention for details. The same safety net applies to remote files.