The DR plan says RTO four hours. Ask where the number came from
and the answer is usually that four hours sounded acceptable to
the business, which is a perfectly good way to set a target
and no evidence at all about the capability.
Setting targets is the subject of the RPO and RTO modelling
lesson. This one is the other half: designing a drill that
produces observed numbers, and comparing the two. When they
disagree - and on a first measurement they nearly always do -
the plan is wrong, not the drill.
Both ends of the clock are usually measured wrong
Read-only / Safeone timestamp, UTC, unambiguous— Every timestamp in a drill log should be UTC and ISO-8601. A drill that spans a daylight-saving boundary, or whose participants are in three time zones, produces arithmetic errors that look like findings. date -u +%FT%TZ is portable across every distribution in this course.
$ date -u +%FT%TZ
2026-08-11T09:00:00Z
Illustrative output
The start. RTO is measured from the incident, not from the
moment somebody types the restore command. Everything before
that is inside it: detection, paging, someone waking up,
establishing what happened, deciding to restore rather than
repair, and getting authorisation to do so. A drill that begins
with the runbook open and the credentials already in hand has
excluded the phase that is most often the longest.
The end. RTO ends when users can use the service, not when
the restore process exits. Between those two points sit a
startup, a health check, a cache that is cold, an index that
must rebuild, a replica that must catch up, a load balancer that
will not mark the backend healthy for another two intervals, and
a DNS record whose TTL is 3600.
Instrumenting the drill
The instrumentation is a shell function and an append-only file.
Nothing more sophisticated is needed, and anything more
sophisticated tends not to get used at 3am.
Read-only / Safewhere the time actually went— The transfer is 5.5 hours of a 9-hour total, and the two phases after the service started add another 2.5 hours. Any effort spent making the restore command faster addresses 60% of the problem; lowering the DNS TTL from 3600 to 60 removes an hour for the cost of one config change. The measurement is what tells you which lever is worth pulling.
2460 s credentials retrieved
540 s target host provisioned
19800 s transfer complete
180 s ownership and labels applied
45 s service started
5400 s health check green
3600 s DNS cut over
Illustrative output
Do the arithmetic before you promise the number
A large restore is bounded by physics before it is bounded by
tooling, and the arithmetic takes thirty seconds.
Data
Sustained rate
Pure transfer time
500 GB
1 Gb/s (~110 MB/s)
1.3 hours
4 TB
1 Gb/s (~110 MB/s)
10.6 hours
4 TB
10 Gb/s (~1.1 GB/s)
1.1 hours
4 TB
200 MB/s (disk-bound)
5.8 hours
If the plan says four hours and the data is 4 TB behind a 1 Gb
link, the plan is arithmetically impossible and no amount of
drilling will fix it. That is a useful finding to produce on a
Tuesday afternoon rather than during an outage.
Measuring RPO instead of asserting it
RPO is routinely reported as the backup interval. It is not. It
is the age of the newest copy you can actually restore from the
location the disaster leaves you with - and there are usually
two or three lags stacked between the last backup and that copy.
Write a sentinel immediately before the drill: a row in the database or a file on the filesystem carrying the current UTC timestamp, so you have a known marker with a known time.
Restore from the copy the scenario dictates. For a host loss that is the local repository. For a site loss it is the offsite copy, which is a different and usually older thing.
Find the newest data present in the restored system - the latest sentinel, or the maximum timestamp in the busiest table.
Measured RPO is the difference between that timestamp and the moment the incident was declared. Not the backup interval.
Repeat for each disaster scenario separately. The numbers differ, sometimes by days, and a single RPO figure in the plan hides that.
Read-only / Safethe actual data horizon— Run against the RESTORED instance, on its own port, never against production. This is the newest row that survived, and the distance between it and the declared incident time is the measured RPO. If the plan claims 24 hours and this is 31 hours old, the difference is the lag nobody had counted - the gap between the backup completing locally and the copy reaching the location you are restoring from.
$ sudo -u postgres psql -Atc "SELECT max(created_at) FROM audit_log"
2026-08-10 02:00:11+00
Illustrative output
What the drill report has to contain
The scenario, named. Host loss, site loss, ransomware, accidental deletion - the measured numbers differ per scenario and an unlabelled number is not usable.
Measured RTO with the clock boundaries stated explicitly: what event started it and what condition stopped it.
Measured RPO, derived from a sentinel, per scenario.
The per-phase breakdown, so the next improvement can be aimed at the phase that dominates rather than at the one that is easiest to change.
Achieved transfer rate in MB/s, with the data volume it was measured against.
The conditions the drill ran under, and which of them a real incident would not have.
Findings with owners. A finding without a name attached is an observation, and observations do not get fixed.
Then, the part that makes all of it worth doing: update the DR
plan with the measured numbers. A plan that still claims four
hours after a drill measured nine is not a plan, it is a
statement of preference, and the gap between the two is exactly
the risk nobody has agreed to accept.
Knowledge check
Knowledge check · 4 questions
Q1. A drill measures a 38-minute restore against a 4-hour RTO and is recorded as a pass. What is most likely wrong with that conclusion?
Q2. Because the backup job sustained 400 MB/s, a restore of the same dataset can be planned at roughly 400 MB/s.
Q3. Which of these make a measured RPO trustworthy? Select all that apply.
Q4. The per-phase breakdown shows 5.5 hours of transfer, 1.5 hours of index rebuild and cache warm-up, and 1 hour of DNS TTL. Which improvement gives the best return for the least effort?
Passing score: 75%. Answers are checked in this browser.