mirror of
https://github.com/borgbackup/borg.git
synced 2026-09-01 14:13:19 +02:00
155 lines
7.3 KiB
Text
155 lines
7.3 KiB
Text
borg prune visualized (count and interval mixed)
|
||
================================================================================
|
||
|
||
Scenario: You use borg to perform daily backups. As backups age, the day-to-day
|
||
changes become less important, so to save storage space you want older archives
|
||
to "thin out" over time while retaining most recent archives. Your backup
|
||
script runs `borg create`, immediately followed by `borg prune`.
|
||
|
||
Assume today is 2026-06-04 and you always start your backups at 16:00. You have
|
||
been creating backup archives starting at 16:00, followed by pruning, on most
|
||
days going back to late 2025. Today, `borg create` took a little longer than
|
||
usual. It's 16:12 now and you run `borg prune`.
|
||
|
||
You want Borg to keep one archive per day for one week, four weekly archives,
|
||
one archive per month for five months, and two yearly backups. For that, you
|
||
use the following command:
|
||
|
||
```
|
||
borg prune \
|
||
--keep-daily 1w \
|
||
--keep-weekly 4 \
|
||
--keep-monthly 5m \
|
||
--keep-yearly 2 \
|
||
--from '2026-06-04 16:00'
|
||
```
|
||
|
||
The `--keep-*` options reflect the intended retention policy exactly. Note the
|
||
different wording in the retention policy for weekly and yearly archives: They
|
||
aren't *interval*-based, but *count*-based.
|
||
|
||
Another important detail here is `--from`. Without it, intervals would be
|
||
calculated relative to the actual start time of `prune` - in this case 16:12.
|
||
Since your backups are always created at 16:00, this 12-minute shift would move
|
||
the cutoff point of intervals and could cause archives near the boundary to
|
||
unexpectedly fall outside the expected time window.
|
||
|
||
By specifying `--from '2026-06-04 16:00'`, all intervals are anchored to the
|
||
intended reference time (16:00), not the moment `prune` happens to run. This
|
||
ensures stable and predictable retention behavior, independent of when `prune`
|
||
actually runs.
|
||
|
||
The first archive was made on 2025-11-15. You missed the backups on 2026-03-31,
|
||
2026-05-24, and 2026-06-03.
|
||
|
||
Below you find an overview of what archives `prune` will keep.
|
||
|
||
Archives kept by the `--keep-daily` rule are marked by a "d" to the right,
|
||
archives kept by the `--keep-weekly` rule are marked by a "w" to the right,
|
||
archives kept by the `--keep-monthly` rule are marked by a "m" to the right,
|
||
archives kept by the `--keep-yearly` rule are marked by a "y" to the right, and
|
||
archives kept by the `--from` rule are marked by a "x" to the right.
|
||
|
||
|
||
Calendar view
|
||
-------------
|
||
2025
|
||
November December
|
||
1 2 3 4 5 6 7
|
||
8 9 10 11 12 13 14
|
||
15y16 15 16 17 18 19 20 21
|
||
17 18 19 20 21 22 23 22 23 24 25 26 27 28
|
||
24 25 26 27 28 29 30 29 30 31m
|
||
|
||
2026
|
||
January February March
|
||
1 2 3 4 1 1
|
||
5 6 7 8 9 10 11 2 3 4 5 6 7 8 2 3 4 5 6 7 8
|
||
12 13 14 15 16 17 18 9 10 11 12 13 14 15 9 10 11 12 13 14 15
|
||
19 20 21 22 23 24 25 16 17 18 19 20 21 22 16 17 18 19 20 21 22
|
||
26 27 28 29 30 31m 23 24 25 26 27 28m 23 24 25 26 27 28 29
|
||
30m31
|
||
|
||
April May June
|
||
1 2 3 4 5 1 2 3w 1d 2d 3 4x
|
||
6 7 8 9 10 11 12 4 5 6 7 8 9 10w
|
||
13 14 15 16 17 18 19 11 12 13 14 15 16 17w
|
||
20 21 22 23 24 25 26 18 19 20 21 22 23w24
|
||
27 28 29 30m 25 26 27 28d29d30d31d
|
||
|
||
|
||
List view
|
||
---------
|
||
|
||
--keep-daily 1w --keep-weekly 4 --keep-monthly 5m --keep-yearly 2
|
||
--------------------------------------------------------------------------------
|
||
1. 2025-11-15 (oldest)
|
||
1. 2026-06-02 1. 2026-05-23 1. 2026-04-30
|
||
2. 2026-06-01 2. 2026-05-17 2. 2026-03-30
|
||
3. 2026-05-31 3. 2026-05-10 3. 2026-02-28
|
||
4. 2026-05-30 4. 2026-05-03 4. 2026-01-31
|
||
5. 2026-05-29 5. 2025-12-31
|
||
6. 2026-05-28
|
||
|
||
2026-06-04 is additionally kept due to `--from`.
|
||
|
||
|
||
Notes
|
||
-----
|
||
|
||
The current day's archive is always kept, because `create` ran after the date
|
||
given with `--from`. For `prune`, it's as if this archive doesn't exist (yet).
|
||
|
||
2026-06-03 was skipped, so no archive can be kept with `--keep-daily` for that
|
||
day. Other than with a *count*-based policy, no compensation is made for an
|
||
*interval* like `--keep-daily 1w`, so the rule simply keeps one archive fewer.
|
||
|
||
2026-05-28 16:00 is exactly one week before `--from`. Since `create` always
|
||
runs after 16:00, the archive created on 2026-05-28 is kept, too. Without
|
||
`--from`, Borg would cut off at 2026-05-28 16:12 instead, which would likely
|
||
mean that the archive created on 2026-05-28 would be pruned. `--from` ensures
|
||
that 2026-05-28 is consistently kept. If you want it consistently pruned, try a
|
||
later reference time, e.g. `--from '2026-06-04 23:59:59'`.
|
||
|
||
2026-05-31 is considered not only by `--keep-daily`, but by `--keep-weekly`
|
||
and `--keep-monthly`, too. The archive is effectively kept by `--keep-daily`,
|
||
but how this affects other rules differs between *count*- and *interval*-based
|
||
policies. For *interval*-based rules like `--keep-monthly 5m` it has no effect:
|
||
The rule simply keeps one archive fewer in that case.
|
||
|
||
For *count*-based rules like `--keep-weekly 4` it has an effect: The policy
|
||
tells Borg to keep 4 weekly archives. Weekly slots are identified by ISO week
|
||
number; in this example the four kept archives cover weeks 18 through 21. If
|
||
2026-05-31 is kept by another rule already, Borg compensates by keeping an
|
||
older archive instead. Consequently, Borg will also keep the 2026-05-03 archive.
|
||
|
||
The week 22 slot is consumed by that same 2026-05-31 archive. Any other
|
||
archive from that week is not kept by weekly, even if it falls within the
|
||
daily window boundary. This is why 2026-05-27 is pruned: it has just fallen
|
||
out of the daily window, and no other rule covers it.
|
||
|
||
Since 2026-05-24 and 2026-03-31 were skipped, Borg substitutes the next best
|
||
candidate for each: 2026-05-23 fills the week 21 weekly slot, and 2026-03-30
|
||
fills the March monthly slot.
|
||
|
||
The implementation of `--keep-monthly 5m` is somewhat special: Borg defines a
|
||
month as a fixed 31-day period, independent of the actual calendar dates
|
||
involved. As a result, `5m` corresponds to 5 × 31 = 155 days. The archive from
|
||
2025-12-31 16:00 is exactly 155 days older than the reference time and is
|
||
therefore retained by `--keep-monthly`.
|
||
|
||
As a result, there are no true yearly candidates. In the absence of a better
|
||
candidate, `--keep-yearly 2` only matches the oldest archive, 2025-11-15.
|
||
|
||
Since interval rules define time windows rather than competing for a fixed
|
||
number of slots, their interplay is simpler than count-based rules. An archive
|
||
is kept by an interval rule as long as it falls within the specified window;
|
||
the next rule simply considers whatever remains.
|
||
|
||
Intervals and counts can be mixed freely. Yearly retention in this example is
|
||
done by retention count instead of intervals. A count rule paired with interval
|
||
rules behaves just as it would if all preceding rules were also counts:
|
||
Archives already kept by earlier rules are excluded from consideration. In this
|
||
example, every yearly slot is consumed by earlier rules; no true yearly
|
||
candidate remains, so the oldest archive at 2025-11-15 is kept to preserve
|
||
rolling backup semantics.
|