PROOF

The proof, published whether it flatters us or not.

A backup nobody has restored is a promise, not a plan. A weekly timer is now scheduled — Sundays 03:30 for the database — to restore a real client database into a throwaway copy, count what came back, and write down the result. One drill has run so far: 24 July 2026, started by hand, and it passed. There is no earlier history, and no failure has been published because none has yet occurred.

Latest restore drill

pass
Document generated 2026-07-24T21:45:00Z. Drill run 2026-07-24T21:40:12Z. Fleet: 16 client databases, 1 operator.
Tables restored 399 Counted in the throwaway copy, not in the live database.
Rows sampled about 25092 Row counts estimated from the restored catalogue.
Age of the backup used 19.2 hours The drill uses the real nightly dump, not a fresh one made for the test.
Time to restore 3.8 seconds Restore and verification only; it is one database, not the whole fleet.
Newest backup on the fleet 18.0 hours old Oldest is 19.4 hours old. Every database is inside 24 hours.
Fault checks every 60 seconds Every result is recorded. Today only the heartbeat and the disk watchdog notify a human.
THE LAST DRILL

What was actually restored, and what happened to it afterwards.

The drill takes the nightly dump of a live client database, restores it into a new throwaway database on a separate name, opens it, counts the tables, estimates the row counts from the restored catalogue, records the timings, and then destroys the throwaway database. The live database is never touched, and nothing is written back into it. It is the database dump that is drilled: a attachments and uploaded documents are not drilled at all yet, and no filestore drill has produced a published result yet.

Client databases restored in this drill: 1, of which 1 came back verified. Which database it was is deliberately not published. The drill ran on 2026-07-24T21:40:12Z. The backup it used was 19.2 hours old at the moment of restore, because the drill deliberately uses the dump that already existed rather than one made for the occasion. 399 tables came back. About 25092 rows were counted, estimated from the restored catalogue rather than compared row by row against the source. The restore and verification together took 3.8 seconds. The drill passed. The throwaway database was destroyed at the end of the run, so nothing is left behind and no copy of client data sits around waiting to be forgotten.

Read the raw restore log →

THE MECHANISMS

Every setting behind that result, including the one that is a limitation.

These are settings on the machines that run the client databases today, not a description of an intention. Each one is checkable during the 14-day trial.

Nightly database dump
Every database is dumped locally at 02:30. Until 24 July 2026 that dump covered the database only: attachments and uploaded documents were not in it, and the filestore artefact in every stored backup taken before that date is 13 bytes. The code fix was deployed on 24 July 2026, and the first backup that contains documents is the run of the night of 24–25 July 2026. Engine: pg_dump. Retention: 30 days. Last local copy: 02:30.
Separate off-site copy
A second copy is taken every day at 03:30 and held with a different provider, so one provider losing a machine — or losing us as a customer — does not take the backups with it. The retention target is 30 daily, 4 weekly, 6 monthly and 2 yearly copies, and there is a three-day hole in it: the local backups and the off-site copies for 21, 22 and 23 July 2026 are missing after a disk-full incident on those days. Publishing that is the reason this page exists. Last off-site copy: 03:30. Provider is separate from the one running the databases.
Point-in-time recovery
Write-ahead logs are archived, so a database can be rolled forward to a chosen moment rather than only to last night's dump — which is what you need when the damage was a bad import at 14:10 rather than a dead disk. The local point-in-time window covers the period since 23 July 2026 at 15:03, and nothing earlier than that.
Backup encryption — a limitation
Transport is TLS. The backups themselves are not encrypted at rest, locally or off-site, and the local pgBackRest repository shares a disk with the database it protects. Both of those are being changed, and until they are, this is what you are buying.
Streaming replication — asynchronous today
PostgreSQL streaming replication to one standby machine, asynchronous today, with synchronous mode in preparation. If the primary is lost, work committed in the last seconds may not have reached the standby. Mode: async. One standby is configured.
Replication lag alerts
A warning is raised at 30 seconds of lag and a critical alert at 120 seconds, because a standby that has quietly fallen behind is a backup you do not have. Both thresholds are live and recorded; like the other 60-second checks, they are not yet routed to a channel that wakes anybody up.
Fault detection — and where it stops
Checks run every 60 seconds across the databases, the containers, the disks and the backup timers, and every result is recorded. Today only two of them reach a human: a heartbeat and a disk watchdog. Routing for the remaining checks is not yet wired up to any channel, so a non-fatal fault may sit in the log until the next working morning.
Autonomous repair, with a rollback
Routine faults — a stalled worker, a container that will not come back, a filling disk — are repaired automatically. The repair then re-reads the real state of the machine, and if the state has got worse it rolls its own change back and escalates to the operator instead of trying again.
Failover is operator-assisted — a limitation
There is no automatic promotion. When the primary dies a human notices the missing heartbeat, confirms how far the standby has replayed and switches over, so recovery is measured in minutes rather than seconds. Anyone selling you a percentage instead of a mechanism is selling you the percentage. Confirmed in the document: automatic failover is off.
THE PROCEDURE

What happens when a machine dies.

Four steps, with the time each one really costs. The third step is where an automatic system would be quicker than we are, and we would rather you read that here than discover it on the day.

  1. Detection A gap in the heartbeat

    The primary stops sending the heartbeat it is expected to send, and the gap is what raises the alarm — the heartbeat and the disk watchdog are the two checks that notify a human today. The 60-second checks record the rest of the state, including replication lag past 30 seconds, but their routing is not yet wired up to any channel, so a fault that is not fatal may sit in the log until the next working morning.

  2. Assessment by a human 2 to 10 minutes, longer overnight

    The operator decides whether the primary is dead or merely slow, and reads how far the standby has replayed. This is the step that costs the most time, and it is the honest reason we publish no uptime percentage: one operator asleep at 04:00 is a real delay, and pretending otherwise would be the part of this page you should not believe.

  3. Promotion of the standby 1 to 3 minutes once the decision is made

    Replication is asynchronous today, so the standby holds what it has managed to replay and no more: work committed in the last seconds before the failure may not have reached it. The operator reads how far the standby got, promotes it, the application is pointed at it, and sessions reconnect. Anything that did not reach the standby has to be re-entered, and work in flight at the moment of failure is retried by the user.

  4. Verification and rebuild Same working day

    The promoted database is checked, the backup timers are re-pointed at it, and the failed machine is rebuilt and re-attached as the new standby so the pair is whole again. The 02:30 dump and the 03:30 off-site copy resume on their normal schedule, and the next weekly drill restores from the new primary.

THE HISTORY

Every drill we have published.

A weekly timer is now scheduled, Sundays 03:30 for the database. One drill has run so far: 24 July 2026, started by hand at 21:40 UTC, and it passed. There is no earlier history, and no failure has been published because none has yet occurred — not because failures would be left out.

Run Databases Backup age Tables Rows sampled Duration Result
2026-07-24T21:40:12Z 1 19.2 h 399 about 25092 3.8 s pass

Next scheduled drill: 2026-07-26T03:30:00Z.

Have your own backup tested, at no charge.

Send an export of whatever you run today. It is restored on a throwaway database, read, and you get the log: what came through clean, what did not, and how old the copy you sent us really was. No charge, and no follow-up call unless you ask for one.