---
title: 'Backup and Resilience'
source: 'https://academia.sh/en/courses/it-fundamentals/backup-and-resilience'
course: 'Information Technology and Systems Fundamentals'
language: en
updated: '2026-09-13T05:08:04+00:00'
license: 'CC BY-SA 4.0'
objectives:
    - 'Runs the snapshot and the backup through the same loss scenario and counts the recovered items separately'
    - 'Compares the backup chain across three types: files required per point, points lost when a file corrupts, and storage'
    - 'Writes the unrecoverable item by name and counts the gap the two methods leave together'
---

# Backup and Resilience

Running the snapshot and the backup through the same seven loss scenarios: the snapshot bringing 8/8 items in three scenarios, the backup bringing 6/8 items in seven scenarios, the two together recovering 48 of 56 items, the number of points lost when a file corrupts being 1, 18, and 1 in full, incremental, and differential backups, and storage splitting into 1,120, 91.3, and 758.2 GiB.

Across four lessons, the boundary was always measured from the same direction: what happens if
someone crosses it. That is not the only way a boundary falls. A storage device fails, a guest is
deleted by mistake, a host becomes unbootable — no one crosses the boundary, yet the guest is still
lost. Virtualization has two answers to this question, and both are called "bringing it back": the
**snapshot** and the **backup**.

They do not bring back the same thing. The snapshot sits on the host, on the same storage device the
guest's image sits on, and its retention is short; the backup sits outside the host, its retention is
long, and its scope is limited by a list. This lesson runs both through the same seven scenarios and
counts **the recovered and unrecovered items separately**.

**VR26 — The fictional validator guest carries eight items.** **VR27 — The snapshot sits on the host,
on the guest image's storage device**; retention is 7 days, the capture interval is 1 hour. **VR28 —
The backup sits outside the host**; retention is 90 days, the capture interval is 24 hours. **VR29 —
Two items sit outside the backup's scope**: local secrets and in-memory session state; this scope gap
was measured in the Servers, Networking and Hardening course, and here it is an input. **VR30 — A
method, if it works in a given scenario, brings back every item in its scope.** **VR31 — The backup
chain is a 28-day window**; the sizes are fictional.

## Two Methods, the Same Loss Scenario

```js
// loss.mjs — snapshot vs. backup in the same loss scenarios: recovered and unrecovered items.
// Fictional validator guest carries 8 items. Scope gaps are an input from the previous course.
const ITEMS = ['operating system root files', 'application binaries', 'configuration',
  'database pages', 'work order queue', 'audit log', 'local secrets', 'in-memory session state'];
const OUT_OF_SCOPE = ['local secrets', 'in-memory session state'];   // outside the backup's scope
const SNAPSHOT = { scope: ITEMS.length, retention: 7, window: 1 };   // on the host, same storage device
const BACKUP = { scope: ITEMS.length - OUT_OF_SCOPE.length, retention: 90, window: 24 };
// [scenario, age of the loss (days), storage device lost, host lost, guest object deleted]
const SCENARIOS = [
  ['guest file system corruption', 0, false, false, false],
  ['misconfiguration (2 hours ago)', 0, false, false, false],
  ['files inside the guest being encrypted', 0, false, false, false],
  ['a record deleted 30 days ago', 30, false, false, false],
  ['loss of the storage device', 0, true, false, false],
  ['loss of the host machine', 0, false, true, false],
  ['guest deleted from the management interface', 0, false, false, true],
];
const snapshotOk = ([, age, b, k, s]) => !b && !k && !s && age <= SNAPSHOT.retention;
const backupOk = ([, age]) => age <= BACKUP.retention;

const s = (x, n) => String(x).padStart(n);
console.log(`${ITEMS.length} items; snapshot scope ${SNAPSHOT.scope}, retention ${SNAPSHOT.retention} days; `
  + `backup scope ${BACKUP.scope}, retention ${BACKUP.retention} days`);
console.log(`\n${'scenario'.padEnd(46)}${s('snapshot', 15)}${s('backup', 9)}${s('best', 10)}`);
let a = 0, y = 0, best = 0;
for (const sen of SCENARIOS) {
  const ka = snapshotOk(sen) ? SNAPSHOT.scope : 0, ky = backupOk(sen) ? BACKUP.scope : 0;
  a += ka; y += ky; best += Math.max(ka, ky);
  console.log(`${sen[0].padEnd(46)}${s(`${ka}/${ITEMS.length}`, 15)}${s(`${ky}/${ITEMS.length}`, 9)}`
    + `${s(`${Math.max(ka, ky)}/${ITEMS.length}`, 10)}`);
}
const T = SCENARIOS.length * ITEMS.length;
console.log(`${'total'.padEnd(46)}${s(`${a}/${T}`, 15)}${s(`${y}/${T}`, 9)}${s(`${best}/${T}`, 10)}`);
console.log(`\nsnapshot works in ${SCENARIOS.filter(snapshotOk).length}/${SCENARIOS.length} scenarios, `
  + `and when it works it brings back ${SNAPSHOT.scope}/${ITEMS.length} items`);
console.log(`backup works in ${SCENARIOS.filter(backupOk).length}/${SCENARIOS.length} scenarios, `
  + `every time with ${OUT_OF_SCOPE.length} items out of scope: ${OUT_OF_SCOPE.join(', ')}`);
console.log(`the two together: ${best}/${T}; unrecoverable ${T - best} items`);
console.log(`data-loss window: snapshot ${SNAPSHOT.window} hour, backup ${BACKUP.window} hours`);
```

```
8 items; snapshot scope 8, retention 7 days; backup scope 6, retention 90 days

scenario                                             snapshot   backup      best
guest file system corruption                              8/8      6/8       8/8
misconfiguration (2 hours ago)                            8/8      6/8       8/8
files inside the guest being encrypted                    8/8      6/8       8/8
a record deleted 30 days ago                              0/8      6/8       6/8
loss of the storage device                                0/8      6/8       6/8
loss of the host machine                                  0/8      6/8       6/8
guest deleted from the management interface               0/8      6/8       6/8
total                                                   24/56    42/56     48/56

snapshot works in 3/7 scenarios, and when it works it brings back 8/8 items
backup works in 7/7 scenarios, every time with 2 items out of scope: local secrets, in-memory session state
the two together: 48/56; unrecoverable 8 items
data-loss window: snapshot 1 hour, backup 24 hours
```

The two columns are incomplete in two different ways. The snapshot is **complete where it works**,
and zero where it does not: it brings back eight of eight items in three scenarios, none in four.
Three of the zeros come from the same cause — the snapshot sits **right next to** the thing that
is lost: when the storage device, the host, or the guest object goes, the snapshots go with it.
The fourth has a different cause; the thirty-day-old record is outside the seven-day retention.

The backup is **incomplete everywhere**: it works in all seven and brings back six items every time.
The two items it misses are written by name — local secrets and in-memory session state — and they
are out of scope regardless of scenario. **The snapshot's shortfall depends on the condition; the
backup's depends on scope.**

The bottom rows give the total: snapshot 24/56, backup 42/56, 48/56 when the better of the two is
picked in every scenario. The two methods do not replace each other, they fill each other's gap —
but the remaining eight items come in no arrangement, and all of them are the out-of-scope items in
the four scenarios where the snapshot does not work. On top of this comes the data-loss window: one
hour for the snapshot, twenty-four hours for the backup.

## The Point You Can Return to When the Chain Breaks

The backup is not a single file either. Taking a full copy every day is the most expensive
arrangement; incremental and differential arrangements lower the cost, and in exchange tie the
points to one another.

```js
// backupchain.mjs — the point restorable when full, incremental, and differential chains break (MODEL).
// 28-day window; full backup on day 0, one point every day after. Sizes are fictional.
const DAYS = 28, FULL_GIB = 40, DELTA_GIB = 1.9, CORRUPT = 10;

// files required to open point d (day numbers)
const REQUIRED = {
  full: (d) => [d],
  incremental: (d) => Array.from({ length: d + 1 }, (_, i) => i),
  differential: (d) => (d === 0 ? [0] : [0, d]),
};
const SIZE = {
  full: () => DAYS * FULL_GIB,
  incremental: () => FULL_GIB + (DAYS - 1) * DELTA_GIB,
  differential: () => FULL_GIB + DELTA_GIB * ((DAYS - 1) * DAYS) / 2,
};
const lost = (type, corrupt) => Array.from({ length: DAYS }, (_, d) => d)
  .filter((d) => REQUIRED[type](d).includes(corrupt));

const s = (x, n) => String(x).padStart(n);
console.log(`${DAYS} days, full backup on day 0; full ${FULL_GIB} GiB, daily delta ${DELTA_GIB} GiB`);
console.log(`\n${'type'.padEnd(13)}${s('files', 6)}${s('files per point', 20)}`
  + `${s(`day ${CORRUPT} corrupt: lost`, 22)}${s('newest restorable', 21)}${s('storage GiB', 14)}`);
for (const type of Object.keys(REQUIRED)) {
  const n = Array.from({ length: DAYS }, (_, d) => REQUIRED[type](d).length);
  const k = lost(type, CORRUPT);
  const sound = Array.from({ length: DAYS }, (_, d) => d).filter((d) => !k.includes(d));
  console.log(`${type.padEnd(13)}${s(DAYS, 6)}${s(n[0] === n[DAYS - 1] ? n[0] : `${Math.min(...n)}-${Math.max(...n)}`, 20)}`
    + `${s(`${k.length} points`, 22)}${s(`day ${Math.max(...sound)}`, 21)}${s(SIZE[type]().toFixed(1), 14)}`);
}
console.log(`\nif the full backup (day 0) is corrupted, points lost: `
  + Object.keys(REQUIRED).map((t) => `${t} ${lost(t, 0).length}`).join(', '));
console.log(`differential requires ${(SIZE.differential() / SIZE.incremental()).toFixed(1)}x the storage of incremental`
  + ` and, when day ${CORRUPT} corrupts, recovers ${lost('incremental', CORRUPT).length - lost('differential', CORRUPT).length}`
  + ' more points');
```

```
28 days, full backup on day 0; full 40 GiB, daily delta 1.9 GiB

type          files     files per point  day 10 corrupt: lost    newest restorable   storage GiB
full             28                   1              1 points               day 27        1120.0
incremental      28                1-28             18 points                day 9          91.3
differential     28                 1-2              1 points               day 27         758.2

if the full backup (day 0) is corrupted, points lost: full 1, incremental 28, differential 28
differential requires 8.3x the storage of incremental and, when day 10 corrupts, recovers 17 more points
```
All three types have the same number of points: twenty-eight. The difference is how tied the points
are to one another. In the full arrangement, every point is one file, and one file's corruption
takes only that point. In the incremental arrangement, opening day 27 requires all twenty-eight of
the twenty-eight files; when the single file on day 10 corrupts, eighteen points go at once and the
newest point restorable drops to day 9. In the differential arrangement, every point is two files,
and day 10 corrupting takes only day 10.

The storage column writes the trade-off: 1,120, 91.3, and 758.2 GiB. The incremental arrangement is
the cheapest and the most fragile; the differential arrangement recovers seventeen more points in
the same corruption, at 8.3 times the storage. **The backup type looks like a storage decision;
measured, it turns out to be a dependency decision.** All three share a weakness in the last row: if
the full backup itself is corrupted, all twenty-eight of the twenty-eight points go at once in both
the incremental and differential arrangements.

## Where the Copy Sits

Chain dependency has been measured; **where** the copy sits is a separate number. The same scenarios
now run over a set of copies.

```js
// copies.mjs — copy distribution: how many copies survive in each scenario (MODEL).
// [name, location, online?, deletable with the same management identity?, recovery minutes]
const COPIES = [
  ['host snapshot', 'host', true, true, 8],
  ['backup on the branch server', 'branch', true, true, 45],
  ['backup in the central object store', 'central', true, true, 210],
  ['offline copy at central', 'central', false, false, 720],
];
const SCENARIOS = [
  ['loss of the host machine', (k) => k[1] === 'host'],
  ['loss of the branch facility', (k) => k[1] === 'host' || k[1] === 'branch'],
  ['loss of the central object store', (k) => k[1] === 'central' && k[2]],
  ['compromise of the management identity', (k) => k[3]],
  ['files inside the guest being encrypted', () => false],
];
const remaining = (list, lost) => list.filter((k) => !lost(k));
const s = (x, n) => String(x).padStart(n);
console.log(`${'scenario'.padEnd(40)}${s('remaining', 11)}   fastest recovery`);
let worst = COPIES.length;
for (const [ad, lost] of SCENARIOS) {
  const k = remaining(COPIES, lost);
  const fastest = k.length ? k.reduce((a, b) => (b[4] < a[4] ? b : a)) : null;
  worst = Math.min(worst, k.length);
  console.log(`${ad.padEnd(40)}${s(`${k.length}/${COPIES.length}`, 11)}   `
    + (fastest ? `${fastest[0]} (${fastest[4]} min)` : 'none'));
}
const locations = new Set(COPIES.map((k) => k[1])).size;
console.log(`\n${COPIES.length} copies, ${locations} locations; remaining in the worst scenario ${worst}`);
const online = COPIES.filter((k) => k[2]);
const after = Math.min(...SCENARIOS.map(([, y]) => remaining(online, y).length));
console.log(`once the offline copy is removed, copies ${COPIES.length} -> ${online.length}, `
  + `remaining in the worst scenario ${worst} -> ${after}`);
```

```
scenario                                  remaining   fastest recovery
loss of the host machine                        3/4   backup on the branch server (45 min)
loss of the branch facility                     2/4   backup in the central object store (210 min)
loss of the central object store                3/4   host snapshot (8 min)
compromise of the management identity           1/4   offline copy at central (720 min)
files inside the guest being encrypted          4/4   host snapshot (8 min)

4 copies, 3 locations; remaining in the worst scenario 1
once the offline copy is removed, copies 4 -> 3, remaining in the worst scenario 1 -> 0
```

In three physical scenarios, at least two copies stay standing. The fourth row is different from the
others: compromising the management identity destroys no hardware, yet it still takes three of the
four copies at once — those three are the online copies the same identity can delete, and location
diversity means nothing here.

The last row is the summary of the measure: when the offline copy is removed, the copy count drops
from four to three, but the copies remaining in the worst scenario drop **from one to zero**.
**Resilience is not the number of copies, but the number of items that can destroy those copies at
the same time.**

## Recovery Testing

All of these numbers rest on one assumption: the backup file is readable. Testing this assumption is
called **recovery testing**; it is the same restore drill from the Servers, Networking and Hardening
course, and it was measured there. With this course's measure, there is only one thing to say: when
recovery testing is not done, the item required to cross the recovery boundary is **one** — one
corrupt file, one out-of-scope item, or one unreadable key — and when that item is in place, the
accessible recovery points are zero.

## Summary

- In seven loss scenarios, the snapshot works in 3 and brings back 8/8 items when it does; the
  backup works in 7 and brings back 6/8 every time.
- The snapshot's shortfall depends on the condition — it sits right next to the thing that is lost;
  the backup's depends on scope, and two items stay outside it regardless of scenario.
- The two methods together recover 48 of 56 items; the remaining 8 items come in no arrangement. The
  data-loss window is 1 hour for the snapshot, 24 for the backup.
- In the twenty-eight-point chain, one file corrupting takes 1 point in the full arrangement, 18 in
  incremental, 1 in differential; storage is 1,120, 91.3, and 758.2 GiB respectively. If the full
  backup itself is corrupted, all 28 of the 28 points go at once in both incremental and
  differential.
- In the four-copy arrangement, the worst scenario is compromise of the management identity, taking
  3 copies at once; once the offline copy is removed, the copies remaining in the worst scenario
  drop from 1 to 0.
- When recovery testing is not done, the item required to cross the recovery boundary is one, and
  when that item is in place, the accessible recovery points are zero.

## Course Wrap-Up

| Lesson | Boundary Name | Items Required to Cross | Items Reached if It Falls |
|---|---|---|---|
| Computer Hardware Components | 8 components, 43 items | remote 1–3, physical 0 | 3–43; firmware alone 43 |
| Operating System Families | admin boundary, 14 requests | 1, 2, 3 by family | 13, 9, 5 requests |
| Installation and Configuration | default boundary, 20 items | 1 risky item | 17 items; 5 after hardening |
| File Permissions and Ownership | permission boundary, 70 requests | 1 at ownership | all of the object's permission decisions; 6 deviations |
| Graphical Interface and Command Line | audit trail boundary, 21 records | 1 deletable item | 10 records invisible; 3 jobs untraced |
| Troubleshooting Method | symptom–cause boundary, 16 possibilities | 3.50 steps; 5.81 in the worst order | 14 scenarios to a single cause; 2 inseparable |
| Hypervisor Types | hypervisor boundary, 19 and 26 items | 1 to the neighbor; 2 and 3 to the hardware | 15/19 and 22/26 |
| Guest and Host System | sharing boundary, 11 items | 1 in 4 paths, 2 in 10 paths, 3 in 2 paths | 6 of 16 paths cannot be closed |
| Virtual Machine Management | clone and snapshot boundary, 7 secrets | 1 for a shared secret | 24 machines; 17 vulnerabilities on rollback |
| Comparison with Containers | isolation boundary, 52 items | guest 2, compartment 1, nested 3 | 39/52, 52/52, nested 9/52 |
| Backup and Resilience | recovery boundary, 56 items | 1 for a corrupt file | 8 items unrecoverable; 18 points |

The third column reads the course's rule the same way across all eleven rows: **isolation is not an
adjective, it is the number of items that must be wrong at the same time to cross the boundary; if
that number is one, there is no boundary.** All eleven of the eleven rows have at least one "1." A
risky default item, an ownership record, a deletable audit record, a shared secret, a corrupt backup
file — each is sufficient on its own, and none of them uses an escape path.

The places where the number is greater than one come from three sources: **layer stacked on layer**
(two and three items to the hardware, three in the nested arrangement), **a verification chain**
(signed boot raises the required item from one to four), and **split privilege** (the admin boundary
is one item in one family, three in the other). All three have their cost written down — four extra
patch items, three links re-signed on every update, nine requests unreachable even as an admin. **A
boundary whose cost is not written down has not been measured.**

The fourth column shows where the boundary is not enough: six sharing paths that cannot be closed,
eight items that cannot be recovered, two causes that cannot be separated, and one installation item
that never closes. None of them close with a better configuration.

All of these numbers were measured on a single machine and the guest systems on it. But the branch
server does not stand alone: meter endpoints and field teams' laptops connect to it, and it in turn
connects to the center. Each of these connections is a path that runs **outside** the boundary the
operating system draws; neither permission bits, nor the hypervisor, nor the compartment sees it.
**M24/K03 Network Security** begins with this question: how many paths does each connection between
two machines open, and who counts those paths.
