Skip to main content

Engineering RPO, RTO, and Uptime

Recovery point, recovery time, and availability are usually written down once, in a document nobody consults, as three numbers that were never checked against a mechanism. This guide is about making them real: stating them per journey, mapping each failure scenario to the mechanism that addresses it, and reconciling the targets against numbers you have actually measured.

If a target and a measurement disagree, one of them has to change. The point of doing this deliberately is that you get to choose which, rather than finding out during an incident that the answer was the target all along.

What You Will Learn

  • How to state recovery point, recovery time, and availability so they are testable rather than aspirational
  • A scenario-to-mechanism map, with what has to be proven for each to count
  • How to convert an availability target into a monthly budget, and what each tier demands of your automation
  • How to reconcile stated targets against the numbers measured in earlier guides
  • Why one storage setting can silently invalidate your stated recovery point
  • Why declaring your degraded modes is as important as declaring your targets

Prerequisites

  • Measured numbers from the earlier guides: per-node capacity, convergence time, node re-entry time, release reversal time, and restore time
  • Sizing a Harper Cluster for the capacity model
  • Backup and Recovery for the recovery mechanisms
  • A named owner who can approve or reject a target, because this exercise produces decisions rather than data

State the three per journey

TermThe question it answersHow to state it so it is testable
Recovery point objectiveHow much recent data may be lostPer database, in units of time, measured against your backup timestamp
Recovery time objectiveHow long until service is restoredPer journey, measured from the moment the journey starts failing, not from the moment someone acts
Availability targetHow much unavailability is permittedPer journey, as minutes per month, with the measurement boundary named

Three details make the difference between a testable statement and a slogan.

Per journey, not per cluster. A catalog browse and an order submission fail differently, matter differently, and recover differently. One cluster-wide number overcommits on the cheap journey and undercommits on the expensive one.

Recovery time starts when the journey breaks, not when someone acts on it. Detection is inside the clock, not before it, and the gap between something breaking and someone knowing is often the largest part of an outage. Starting the count at the moment a human decided to act, or even at the moment an alert fired, produces a number that flatters your automation and misleads your planning. Your users were already down for all of it.

Name the measurement boundary. Availability measured at your CDN edge and availability measured at a Harper node are different quantities, and the difference is exactly the part of the stack you may not control. Whichever you choose, say so in the same sentence as the number.

One storage setting can override your recovery point

Your recovery point objective is a statement about how much acknowledged data you can afford to lose. One configuration option can quietly make that statement false.

storage.writeAsync defaults to false. Set it to true and Harper stops calling fsync on commit, so a write returns as soon as it is queued to the operating system's page cache. Throughput on write-heavy workloads improves substantially. The cost is that a power loss or OS crash between the commit and the flush to disk loses the most recent transactions, even though your application was told they succeeded. The database stays structurally consistent; only the newest writes are gone.

The trap is that this is invisible to everything else in this guide. Backup timestamps look right, replication looks healthy, and no alert fires. You discover it the first time a node loses power, which is also the first time the gap between your stated recovery point and your real one matters.

So treat it as an RPO decision rather than a performance one. Enabling it is defensible when the data is reproducible from an upstream source, when the workload is bulk ingest that can simply be re-run, or when peers acknowledge writes before the loss window opens. Outside those cases, leave it off. If it is on anywhere, record which databases and say so next to the recovery point in your plan, because the number no longer means what it appears to.

Map scenarios to mechanisms

For each scenario, know the mechanism, and know what must be proven for the mechanism to count. The right-hand column is the whole exercise.

ScenarioPrimary mechanismWhat must be proven
Single node lossPeer capacity plus traffic removal(N - F) capacity under load, measured time to remove traffic, no user-visible errors in transition
Node returns after a restartIncremental catch-up plus an admission gateMeasured convergence time, and an admission gate that does not admit before convergence completes
Node replacement or scale-outFull database synchronization to the new nodeMeasured full-sync duration at your data volume, and the load it puts on the source node
Failure domain lossTopology spread across independent domainsNo shared power or network fault, and surviving capacity inside the budget
Region lossMulti-region topology plus route changeData authority per region, route propagation time, and declared degraded behavior
Bad release, no data changeRelease reversalMeasured release reversal time, and the previous artifact still addressable
Bad release that changed data meaningForward repair, not restoreA written repair or replay procedure, rehearsed on representative data
Accidental destructive operationRestore from backupMeasured restore time and actual data loss, from a real drill
Storage loss on one nodeOff-host backup copyA restorable off-host copy, taken by the correct procedure for your mechanism
Corruption propagated by replicationRestore the last good backup, plus a replication decisionA rehearsed sequence that includes what happens to peers
Replication certificate expiryCertificate lifecycle managementExpiry dates tracked, with an alert far enough ahead to act
Downstream dependency outageDeclared degraded modeThe journey's behavior when the dependency is down, verified rather than assumed

Two rows in that table are the ones most often missing. Node replacement is budgeted as though it were a restart, when it is a full synchronization and can be much slower. And the downstream dependency row usually has no answer at all, which means the answer is whatever the code happens to do.

Convert availability into a budget

An availability target is a quantity of unavailability you may spend per month.

Monthly targetApproximate maximum unavailabilityWhat the tier demands
99.9%43 min 50 secA human can be paged, diagnose, and act within some incidents. One untested maintenance window can consume the month
99.95%21 min 55 secAutomated traffic removal and a rehearsed release reversal become necessary rather than nice
99.99%4 min 23 secNode failure has to be close to transparent. Detection, traffic removal, and validation must be automated, since no human response fits

Figures assume a 30.44 day month. Your contractual definition, exclusions, and measurement boundary may differ.

Read down that right-hand column rather than the middle one. The tier you choose determines how much automation you are committing to build, not how many nodes you buy. Adding nodes without automating detection and traffic removal moves you across the table's rows without moving you down its column.

Treat the budget as spendable. If the month's remaining budget is small, that is an argument for pausing discretionary change, and if it is large, that is permission to ship. An error budget that never changes anyone's behavior is just a number in a document.

Reconcile targets against measurements

This is the step that turns the exercise into engineering. Fill in both columns and look for rows where they disagree.

CommitmentMeasured fromYour targetYour measurement
Surviving capacityThe peak-load drain drill in Sizing
Time to remove trafficThe drain sequence in Health Checks
Node re-entry timeThe same drill, including convergence
Convergence time under loadThe sentinel measurement in Operating Replication
Full synchronization timeA node replacement at your data volume
Release reversal timeThe stopped-rollout rehearsal in Safe Deployments
Restore timeThe restore drill in Backup and Recovery
Actual data loss on restoreThe same drill, against the backup timestamp
Time to detectionThe fault injection drill in Monitoring and Triage

Three reconciliations catch most problems:

  • Backup cadence against recovery point. If you back up every six hours, your recovery point cannot be one hour, no matter what the document says.
  • Restore time plus detection time against recovery time. Recovery time includes noticing. A twenty minute restore behind a forty minute detection gap is a one hour recovery.
  • Convergence time against your admission gate. If your gate admits a node faster than it converges, you are serving stale data on purpose and calling it availability.

Where a target and a measurement disagree, the resolution is one of three things: invest in the mechanism, relax the target, or accept the gap explicitly with an owner and a date. All three are legitimate. Leaving it unreconciled is not.

Declare your degraded modes

Between fully working and fully down there is a range of states, and if you have not decided what they should be, the code has decided for you.

For each critical journey, write down what happens when a dependency is unavailable, when a node is behind on replication, and when the cluster is below its capacity budget. Reads served from slightly stale data may be entirely acceptable for a catalog and entirely unacceptable for a balance check, and the right answer differs by journey rather than by system.

Then decide who can declare a degraded mode, and whether the declaration is manual or automatic. A degraded mode nobody is authorized to invoke is not a degraded mode.

Prove it

Two passes, and both are needed.

Tabletop the whole scenario table. For each row, walk through who detects it, what they do, what mechanism carries the recovery, and what evidence confirms success. Rows where the group cannot answer without speculating are the gaps, and finding them costs an hour rather than an outage.

Then run one real drill per scenario class, spread over a quarter rather than attempted in a day. The classes are: node loss, node return, node replacement, release reversal, restore, and dependency failure. Record the date, the measured numbers, what surprised you, and what you changed as a result.

The surprises are the deliverable. A drill that goes exactly as expected has confirmed your documentation. A drill that does not has found the thing that would have hurt you.

Operational notes

  • Recovery numbers expire. Every measurement here is a property of a Harper version, a data volume, a topology, and a set of components. Re-measure after version upgrades and significant data growth, and date every number you record.
  • Uptime and recovery targets belong in the same document as the mechanism. A target stored separately from its supporting evidence drifts from reality within a quarter.
  • Do not let a single incident rewrite your targets. Adjust targets from measurement and business need, not from the last thing that went wrong.
  • Exclusions matter as much as the number. Planned maintenance, third-party dependency failures, and client-side problems are usually excluded from an availability calculation. Whether yours excludes them changes the number substantially, so it belongs in writing.
  • A target you cannot measure is not a target. If nothing in your monitoring produces the number in your commitment, the first investment is measurement, not more nodes.

Readiness checklist

  • Recovery point stated per database, in time units
  • Recovery time stated per journey, measured from the start of failure and including detection time
  • Availability stated per journey, with the measurement boundary named
  • Exclusions documented
  • Every scenario in the map has a named mechanism
  • Every mechanism has its "what must be proven" satisfied or explicitly outstanding
  • Availability target converted to minutes per month
  • Error budget policy states what changes when the budget runs low
  • Backup cadence reconciled against recovery point
  • storage.writeAsync confirmed off, or the databases it is on for recorded alongside their recovery point
  • Restore time plus detection time reconciled against recovery time
  • Convergence time reconciled against the traffic admission gate
  • Every unreconciled gap has an owner and a date
  • Degraded modes declared per journey, with authority to invoke them
  • Tabletop completed and dated
  • At least one real drill per scenario class completed and dated

Additional Resources