Planning & scheduling
A multilevel schedule driven by only two inputs — the cycle and the medium’s capacity — with no per-DLE balancing knobs to tune.
Two inputs, no knobs
NBackup plans backups on a multilevel scheme (levels 0–9): level 0 is a full, levels 1–9 are progressively smaller incrementals. The whole schedule is driven by just two numbers you already set:
cycle— the target and hard-maximum time between fulls of each DLE.- the landing medium’s
capacity— the space NBackup may use there.
There are no balancing knobs, no per-DLE schedules, no “full on Sunday” calendar. The planner derives everything from the cycle and capacity, re-deciding on every run from fresh size estimates.
What each run decides
Every run makes three decisions, in order.
1. Estimate
The run sizes every DLE first — its full size and its incremental at the current
level and the next — by running the dump method against /dev/null. GNU tar walks
the file metadata without reading file bodies, so the estimate is fast yet honors
your excludes, one-file-system, and the incremental snapshot exactly. Sizes are
uncompressed — an upper bound on the bytes that will land.
nb status shows this as an estimating phase while it runs, so a long initial
sizing pass on a large source reads as “underway”, not “nothing happening”.
2. Pick a level
Per DLE, in priority order:
- Never fulled → a mandatory level 0.
- At or past the cycle deadline → a forced level 0. The cycle is a hard ceiling: a full never ages past it, so a full is either due or it isn’t.
- Otherwise → an incremental, governed by the bump rule below.
The bump rule
A DLE does not climb a level every run. After a full it sits at level 1, re-dumping everything changed since the full. It climbs to a deeper level only when both hold:
- it has held the current level for a couple of runs — so the climb rests on the level’s demonstrated steady state, not a single run’s estimate — and
- climbing would save at least
bump_percentof the full size (default 5%).
The savings from climbing shrink as levels deepen, so in practice level 1 is the common case and deep levels are earned by real savings. The payoff: restore chains stay short, and consecutive same-level incrementals overlap and stay independent of one another — losing one costs at most its own restore point, never the runs after it.
The bump rule is not a redundancy mechanism — it can’t be: the full, which every incremental depends on, gets no overlap. Redundancy in NBackup is copies to a second medium, which protect the full and incrementals alike; see Replication.
cycle: 7d
bump_percent: 5 # climb a level only when it saves >= 5% of the full size
3. Promote to balance
Promotion is the only balancing lever, and it is automatic — there is no knob. The planner builds a deadline calendar of every DLE’s upcoming full and then, each run, repeatedly pulls whichever future full onto today most flattens the daily load — lowering the heaviest day first, then evening out the rest — so a clump of DLEs sharing a deadline is spread across distinct days instead of piled onto one night. Every move must clear two guards:
- No overshoot — a full is pulled forward only when today ends up no heavier than the day it relieves. This forbids merely relocating a peak: a lone big DLE is never re-fulled early (moving it would just move the same peak onto today), and it means a shared-deadline clump is a phase-shift onto other days, not extra fulls — each DLE still fulls once per cycle.
- It fits the per-run room left (see Two capacity limits).
With no free capacity, promotion does nothing. Where DLEs are comparable in size, flattening a clump can cut the peak night dramatically (e.g. twelve equal DLEs sharing a deadline: a 6-high pile becomes ~2 per night). Where one DLE dominates, its night is the irreducible peak — promotion can’t lower it, but still spreads the smaller fulls off it so fewer land on the same night.
This is what de-clumps the cold start: day one fulls everything (recoverability first), and promotion staggers that lock-step apart over the next cycle or two, so later runs don’t all come due together.
Two capacity limits
Capacity is the one number you give a medium, and it binds at two scopes:
| Scope | What must fit | How it’s bounded |
|---|---|---|
| Per run | A single run’s peak size. | Promotion is capped at the room left before pruning would evict a protected run (capacity − protected set), tightened further by the landing volume’s free space. No room → no promotion. A run can still be lumpy when a big DLE hits its own deadline — that full is mandatory, not promoted. |
| Per cycle | A complete recovery set: one full of every DLE. They coexist while minimum_age ≥ cycle, so Σ full_est must fit capacity. |
Structural — no scheduling can change the cycle’s fixed full demand. |
When Σ full_est exceeds capacity, the plan carries a warning: recoverability
is at risk, but backups still run. It is the signal to grow capacity or
lengthen the cycle, rather than silently pruning the oldest recovery points away.
The priority order is immovable — recoverability and cycle safety come first;
capacity only bounds balancing.
Forecasting
Two commands let you see the schedule before it happens.
nb plan --days N projects the planner forward over N daily runs, advancing a
copy of the history after each simulated run — so you see when each DLE’s next
full lands and how its incrementals bump in between, not just today’s decision
repeated. Estimates and the capacity ceiling are sampled once and held constant
(a level-schedule forecast, not a capacity timeline); nothing is written.
nb dump --dry-run [--date <day>] is the single-run dry run: it plans the run
for --date against the current catalog — the exact decision a real nb dump
--date <day> would make — and prints it without writing anything.
nb plan # today's plan: levels, capacity usage, cost
nb plan --days 30 # forecast the next 30 daily runs
nb dump --dry-run # plan today's run; write nothing
nb dump --dry-run --date 2026-07-15 # plan a specific future day
The planner consumes only bytes — it never knows whether the landing medium is a disk, a tape library, or an object store.
Next: Cost forecasting turns these byte forecasts into $/month for cloud
media; Pruning & retention covers how runs are reclaimed to stay within
capacity; Storage media covers where runs land.