Hi all,
I’m looking for confirmation/guidance on Proxmox Backup Server retention behavior. I’ve read the docs, but in my tests the results don’t match expectations, and I’d like to understand whether I’m misreading the rules or there’s something off.
TL;DR
--keep-last 3
--keep-hourly 48
--keep-daily 30
--keep-monthly 6
--keep-yearly 1
When I run:
proxmox-backup-client prune vm/107 \
--repository root@pam@localhost:Backup \
--ns pve-r420 \
--keep-last 3 --keep-hourly 48 --keep-daily 30 --keep-monthly 6 --keep-yearly 1 \
--dry-run
all snapshots are reported as keep, including the ones from July (starting 2025-07-19).
Snapshot list (excerpt):
vm/107/2025-07-19T21:06:05Z keep
vm/107/2025-07-20T21:09:19Z keep
...
vm/107/2025-08-xx... keep
...
vm/107/2025-09-xx... keep
...
vm/107/2025-10-07T21:10:23Z keep
As of today I count 81 snapshots (Jul 19 → Oct 7), all marked keep in dry-run.
From the manual:
So expected outcome: ~30 recent daily snapshots + 1 per month (6) + maybe 1 yearly → around ~37 snapshots (give or take), not 81.
Thanks a lot to anyone willing to help me understand where I’m going wrong or what I’m missing about the combined behavior of the rules.
I’m looking for confirmation/guidance on Proxmox Backup Server retention behavior. I’ve read the docs, but in my tests the results don’t match expectations, and I’d like to understand whether I’m misreading the rules or there’s something off.
TL;DR
- PBS 4.0.15, datastore Backup, namespace pve-r420, VM 107 (~732 GiB/snapshot), daily backups since 2025-07-19.
- Retention policy on prune job: --keep-last 3 --keep-hourly 48 --keep-daily 30 --keep-monthly 6 --keep-yearly 1.
- Expectation: ~30 recent dailies + ~6 monthlies (+ maybe 1 yearly) ⇒ ~35–40 snapshots total.
- Observed: dry-run marks all ~81 snapshots as keep (including July/August). Running prune + GC frees nothing.
- Verified: no Protected snapshots; correct namespace; regular daily schedule; GC run after prune.
- Suspected cause: keep-daily counts “days with backups” (skips empty days), so the 30-day window stretches far back, effectively keeping whole months; keep-monthly then adds nothing visible.
- Asks:
- Is this behavior correct for keep-daily + keep-monthly?
- Can dry-run show which rule keeps each snapshot? (feature?)
- Best practice: split namespaces per retention class for big/low-dedup VMs? (Confirm dedup is per-datastore, not cross.)
- Any known caveats in 4.0.15 with these rules?
Environment
- PBS: 4.0.15
- Datastore: Backup (single)
- Namespace: pve-r420
- VM under test: VM 107 (QEMU), daily snapshots since July; per-snapshot size ~732 GiB
- No snapshots are protected (Protected flag is off)
Goal
Reduce space while keeping:- a reasonable daily window (30 days),
- 6 monthlies,
- 1 yearly,
- plus a small safety net via keep-last.
Retention policy set on the namespace prune job
--keep-last 3
--keep-hourly 48
--keep-daily 30
--keep-monthly 6
--keep-yearly 1
Commands used (dry-run) and unexpected result
When I run:
proxmox-backup-client prune vm/107 \
--repository root@pam@localhost:Backup \
--ns pve-r420 \
--keep-last 3 --keep-hourly 48 --keep-daily 30 --keep-monthly 6 --keep-yearly 1 \
--dry-run
all snapshots are reported as keep, including the ones from July (starting 2025-07-19).
Snapshot list (excerpt):
vm/107/2025-07-19T21:06:05Z keep
vm/107/2025-07-20T21:09:19Z keep
...
vm/107/2025-08-xx... keep
...
vm/107/2025-09-xx... keep
...
vm/107/2025-10-07T21:10:23Z keep
As of today I count 81 snapshots (Jul 19 → Oct 7), all marked keep in dry-run.
What I expect (based on docs)
From the manual:
- keep-last=3: keeps the last 3 snapshots (likely also covered by hourly/daily).
- keep-hourly=48: in my case adds little (I do one backup per day around 21:00).
- keep-daily=30: 1 backup for each of the last 30 days that have a backup. I know days without backups don’t count, so if I skipped e.g. 2–3 days in September, the window stretches back to cover 30 backup-days. Still, I’d expect July to be out (unless there were huge gaps).
- keep-monthly=6: the latest backup of each of the last 6 months; typically I’d expect 1 for September, 1 for August, 1 for July, etc. (but not every daily of those months!)
- keep-yearly=1: the latest of the year.
So expected outcome: ~30 recent daily snapshots + 1 per month (6) + maybe 1 yearly → around ~37 snapshots (give or take), not 81.
What actually happens
- With the policy above, none of the older snapshots are flagged remove in dry-run (including July).
- Running prune and then GC, disk usage doesn’t change notably (consistent with dry-run).
Checks already done
- Protected: no snapshot has the flag set.
- Namespace: correct (I use --ns pve-r420 everywhere).
- Snapshot list: verified; they’re indeed daily and regular.
- GC: run after prune; shows “removed-chunks: 0” when dry-run marked nothing to remove.
Specific questions
- keep-daily=30: Is it correct that to cover “30 days with backups” PBS can end up including all days of July and August, even when September/October have daily backups with only a few gaps?
– I understand “days without backups do not count”, but I’d like confirmation in practice where daily seems to “stretch” so far back that even entire months remain fully kept, not just one day per month. - keep-monthly=6: Please confirm it should keep one snapshot per month (the most recent of each month) in addition to those already covered by daily.
– In my case, daily appears to stretch enough to include all days of July/August, making the monthly aggregation effectively moot. - Is there a way (CLI or API) for dry-run to also show which rule keeps a snapshot (e.g., “kept by daily/monthly/last/yearly”) so we can understand why each snapshot stays?
– If not, would this make sense as a feature request? It would be super helpful for troubleshooting. - Am I approaching this wrong, and should I segment into namespaces per retention class (e.g., ns/short, ns/medium, ns/long) and apply more aggressive policies to VMs with poorly-deduplicable datasets (large DB/mailstore)?
– If yes, please confirm that dedup is per-datastore and not cross-datastore. - Lastly: are there any known caveats in 4.0.15 around these prune rules?
Extra data (if useful)
- Example command I use to count unique backup days (to validate “days without backups do not count”):
- proxmox-backup-client snapshot list \
--repository root@pam@localhost:Backup --ns pve-r420 | \
grep 'vm/107' | awk '{print $2}' | cut -d'T' -f1 | sort | uniq | wc -l
(happy to post the output) - I can also share proxmox-backup-manager prune-job show <ID> and full prune logs.
Thanks a lot to anyone willing to help me understand where I’m going wrong or what I’m missing about the combined behavior of the rules.
Last edited: