Data resilience
5 stores · 6/11 copies running · register proposedWhere every store this estate cannot afford to lose is written, where its copies are, how each one is fed, and what a schema change does to all of it. Recovery points are derived from the copies, never declared, and they are measured against what is running today — a copy that is planned protects nothing yet.
Open gaps
Measured against what is running, not what is designed-
Open gap: Every copy that leaves the primary’s domain is fed over the home uplink. jarvisos-postgresEvery running copy of JarvisOS Postgres that leaves fd-home-rack is fed over the home uplink (mesh, home-egress). While that uplink is down the primary keeps accepting writes and none of them are protected off-site — and nothing looks broken. pg-offsite-vin would close this once running.
-
Open gap: The best copy is fed more slowly than the declared recovery point allows. jarvisos-vin-journalJarvisOS VIN journal has no running copy anything can be recovered from. Planned: journal-offsite-s3.
-
Open gap: No copy outside the primary’s failure domain meets the declared site recovery point. jarvisos-vin-journalJarvisOS VIN journal has no running copy outside fd-vps, so losing the site loses everything ever written to it. Planned: journal-offsite-s3.
-
Open gap: Every copy of this store sits in the same failure domain as the primary. jarvisos-vin-journalJarvisOS VIN journal and every running copy of it sit in fd-vps. That domain’s correlated risks are this data’s risks. Planned: journal-offsite-s3.
-
Open gap: Nothing leaves the estate, so no copy survives the site. jarvisos-vin-journalJarvisOS VIN journal has no running copy in a domain that hosts none of our compute. Planned: journal-offsite-s3.
-
Open gap: Nobody has proven the queue drains after an outage. jarvisos-vin-journalJarvisOS VIN journal has never had a disconnect-and-drain proven end to end.
-
Open gap: Nobody has ever restored this store. jarvisos-vin-journalNobody has ever restored JarvisOS VIN journal from journal-offsite-s3.
-
Open gap: A critical store has no reachable copy at all in a declared scenario. jarvisos-vin-journal"VIN (the VPS) is gone" destroys vin, and every copy of JarvisOS VIN journal that runs today is on it. The data is gone, not merely unreachable. Planned: journal-offsite-s3.
-
Open gap: A writer on another site writes across the home uplink with nothing local to fall back to. jarvisos-sessionsjarvisos-auth on vin writes through a proxy to JarvisOS sessions & queue (Redis) over "mesh", which crosses the home uplink. While that is down, vin cannot write at all.
-
Open gap: No copy outside the primary’s failure domain meets the declared site recovery point. coolify-stateCoolify's own Postgres has no running copy outside fd-home-rack, so losing the site loses everything ever written to it. Planned: coolify-dump-nas, coolify-dump-offsite.
-
Open gap: Fewer independent copies than policy requires. coolify-stateCoolify's own Postgres exists in 2 place(s) today; policy wants 3. Planned: coolify-dump-nas, coolify-dump-offsite.
-
Open gap: Every copy of this store sits in the same failure domain as the primary. coolify-stateCoolify's own Postgres and every running copy of it sit in fd-home-rack. That domain’s correlated risks are this data’s risks. Planned: coolify-dump-nas, coolify-dump-offsite.
-
Open gap: Nothing leaves the estate, so no copy survives the site. coolify-stateCoolify's own Postgres has no running copy in a domain that hosts none of our compute. Planned: coolify-dump-nas, coolify-dump-offsite.
-
Open gap: Nobody has ever restored this store. coolify-stateNobody has ever restored Coolify's own Postgres from coolify-dump-nas.
-
Open gap: A critical store has no reachable copy at all in a declared scenario. coolify-state"Home1 is gone" destroys home1, and every copy of Coolify's own Postgres that runs today is on it. The data is gone, not merely unreachable. Planned: coolify-dump-nas, coolify-dump-offsite.
-
Open gap: Fewer independent copies than policy requires. supabase-edgeSupabase (edge database) exists in 2 place(s) today; policy wants 3. Planned: supabase-dump-offsite.
-
Open gap: Nothing leaves the estate, so no copy survives the site. supabase-edgeSupabase (edge database) has no running copy in a domain that hosts none of our compute. Planned: supabase-dump-offsite.
-
Open gap: Every copy that leaves the primary’s domain is fed over the home uplink. supabase-edgeEvery running copy of Supabase (edge database) that leaves vendor-supabase is fed over the home uplink (vendor-api). While that uplink is down the primary keeps accepting writes and none of them are protected off-site — and nothing looks broken.
-
Open gap: Nobody has ever restored this store. supabase-edgeNobody has ever restored Supabase (edge database) from supabase-dump-nas.
-
Open gap: A rollback path has never been executed. jarvisos-postgresThe rollback for "Drop the legacy heartbeats table" has never been executed against anything.
-
Open gap: A rollback path has never been executed. jarvisos-vin-journalThe rollback for "Journal schema v2 — add a node sequence" has never been executed against anything.
Recovery matrix — by design
From the operator's side of each breakDerived from the copies below, never declared. Writable and auto failover need nobody; reads only means a copy here keeps serving while writes wait for a promotion; restore required means the only thing reachable is a backup.
| Store | Home1 is gone | VIN (the VPS) is gone | Home internet is down | The mesh is partitioned | The NAS is gone |
|---|---|---|---|---|---|
| JarvisOS Postgres | Reads only | Writable | Writable | Writable | Writable |
| JarvisOS VIN journal | Writable | Lost | Lost | Lost | Writable |
| JarvisOS sessions & queue (Redis) | Restore required | Writable | Writable | Writable | Writable |
| Coolify's own Postgres | Lost | Writable | Writable | Writable | Writable |
| Supabase (edge database) | Writable | Writable | Restore required | Writable | Writable |
Recovery matrix — today
Counting only copies that are actually running| Store | Home1 is gone | VIN (the VPS) is gone | Home internet is down | The mesh is partitioned | The NAS is gone |
|---|---|---|---|---|---|
| JarvisOS Postgres | Reads only | Writable | Writable | Writable | Writable |
| JarvisOS VIN journal | Writable | Lost | Lost | Lost | Writable |
| JarvisOS sessions & queue (Redis) | Restore required | Writable | Writable | Writable | Writable |
| Coolify's own Postgres | Lost | Writable | Writable | Writable | Writable |
| Supabase (edge database) | Writable | Writable | Restore required | Writable | Writable |
Transports
What each copy crosses to get where it is goingWhether a path depends on the home uplink is walked through the inventory, not declared: the mesh tunnel does not mention the ISP uplink, it depends on it.
| Path | Crosses | Home uplink | What it is |
|---|---|---|---|
| Home LAN | nothing that leaves the room | no | home1 to nas over the rack switch. Crosses nothing that leaves the room, which is exactly why it protects against nothing that happens to the room. |
| WireGuard mesh | wireguard-tunnel | yes | home1 to vin over the tunnel. The tunnel depends on the ISP uplink, so anything sent this way stops when the home internet does — whether or not the copy says so. |
| Home uplink to the internet | isp-uplink | yes | home1 or nas pushing straight out to a provider. One connection, one router, one ISP. |
| VPS network to the internet | vin | no | vin pushing straight out over the provider's network. Shares no equipment with the house, which is the entire reason it exists in this register. |
| Vendor API from home | isp-uplink | yes | home1 pulling from a provider's API over the home uplink. |
The stores
Each store this estate cannot afford to lose, with both of its recovery points, every copy and what it takes to get it back.
JarvisOS Postgres fleet-fatal postgres
postgres-primary · No signalTask state, the scheduler's leader lease, node identities and every record of what JarvisOS has done. Losing it does not degrade the estate, it forgets it.
- Written by
- single writer — one primary, promotion is a separate act, primary on home1
- Recovery point — anywhere
- 30s today · promised 15m
- Recovery point — losing the site
- 30s today · promised 1h
- Copies
- 5 today, 6 by design, across fd-vps, fd-home-rack, fd-offsite
- Last restore drill
- 2026-07-12 · pass in 22m
- Home uplink
- writes do not cross it; every off-site copy crosses it
Copies
| Copy | Kind | Where | Domain | Path | Behind by | Use |
|---|---|---|---|---|---|---|
| pg-replica-vin | streaming replica | postgres-replica | fd-vps off-domain | mesh via home uplink | 30s | promotable serves reads |
| pg-wal-nas | WAL archive | nas-backups | fd-home-rack | home-lan | 5m | restorable |
| pg-base-nas | snapshot | nas-backups | fd-home-rack | home-lan | 6h | restorable |
| pg-offsite-home | snapshot | gwscli-s3-offsite | fd-offsite off-domain | home-egress via home uplink | 1d | restorable |
| pg-offsite-vin planned | snapshot | gwscli-s3-offsite | fd-offsite off-domain | vps-egress | 6h | restorable |
Promotion — manual, from pg-replica-vin
- Confirm home1 is genuinely gone, not merely slow: the mesh is down and the console shows no heartbeat for 3 intervals.
- Fence: from VIN, drop the mesh route to home1 so a returning primary cannot be written to.
- Record the replica's last replayed LSN in the incident. That number is the data loss.
- pg_ctl promote on postgres-replica; wait for it to leave recovery.
- Repoint the JarvisOS control-plane standby unit on VIN at the local Postgres and start it.
- Announce read-write on VIN in the incident, with the LSN and the loss window.
Fenced by: home1 is fenced before the replica is touched: stop the JarvisOS control-plane unit, `systemctl stop postgresql`, and take the mesh route down from VIN. Only then does the replica get promoted. The old primary never returns as a primary — it is rebuilt as a replica of the new one.
Verified by: The console's own writes land: create and resolve a scratch incident, then confirm it survives a restart of the control-plane unit.
Costs: Everything committed on home1 and not yet replayed on the replica — 30s of writes at the declared lag, more if the mesh was already degraded when home1 died. The promotion records the LSN so the number is known rather than guessed.
Getting redundancy back: Redundancy is gone the moment the replica is promoted: there is one copy again. Within 24h, take a fresh base backup from the new primary on VIN to gwscli-s3-offsite, and rebuild home1 as a streaming replica of VIN when the site returns. The estate stays at reduced protection until both are done, and the incident stays open until then.
Restore — from pg-wal-nas
- Pick the target time. For corruption or a bad migration, that is the minute before it landed; for hardware loss it is 'latest'.
- Restore the newest pg-base-nas snapshot into a scratch data directory — never over the live one.
- Set restore_command against the WAL archive and recovery_target_time, then start Postgres and let it replay.
- Verify (below) before anything is repointed at it.
- Stop the control plane, swap the data directories, start Postgres, start the control plane.
Verified by: Row counts on the three tables that matter (tasks, node_identities, incidents) against the last known-good figures in the incident, plus `SELECT pg_is_in_recovery()` returning false and one write that survives a restart.
- 2026-07-12 — pass, 22m, into scratch instance on home1, port 5433. Point-in-time restore to 24h earlier from pg-base-nas + pg-wal-nas. 22 minutes wall clock, of which 14 was WAL replay. Off-site copies were not exercised.
- The scheduler's leader lease lives in this store on purpose: whoever can write the lease row is by definition the side that can write the data. See docs/CONTROL-PLANE-HA.md.
- The 2026-07-12 drill restored from the NAS, which is in the same room as the primary. The restore that matters — from gwscli-s3-offsite, onto VIN, with nothing at home reachable — has never been run. That is the quarterly drill this register exists to schedule.
- Home1 is gone: pg-replica-vin keeps serving reads here; writes resume once a human promotes it.
- VIN (the VPS) is gone: The primary is on this side. Reads and writes continue.
- Home internet is down: The primary is on this side. Reads and writes continue.
- The mesh is partitioned: The primary is on this side. Reads and writes continue.
- The NAS is gone: The primary is on this side. Reads and writes continue.
JarvisOS VIN journal estate-critical sqlite proposed
not in the inventoryLets VIN keep working when the home uplink does not. Task results, telemetry and evidence are written here first and drained into Postgres when the mesh returns, so a home internet outage costs latency rather than work.
Not watched: Planned. Nothing runs on VIN to declare yet, so the inventory has no entity for it and the health engine cannot see it.
- Written by
- local-first — writes land locally and drain later, primary on vin
- Recovery point — anywhere
- none today (15m by design) · promised 15m
- Recovery point — losing the site
- none today (15m by design) · promised 15m
- Copies
- 1 today, 2 by design, across fd-offsite, fd-vps
- Last restore drill
- never
- Home uplink
- writes do not cross it; no off-site copy crosses it
Copies
| Copy | Kind | Where | Domain | Path | Behind by | Use |
|---|---|---|---|---|---|---|
| journal-offsite-s3 planned | snapshot | gwscli-s3-offsite | fd-offsite off-domain | vps-egress | 15m | restorable |
Local-first writes
Drains into jarvisos-postgres. Queued writes survive a restart. Bounded at 4320m / 2048MB.
When both wrote: There is nothing to merge. Every row carries the node id that wrote it and a monotonic per-node sequence, and only jarvisos-worker on VIN writes them. Postgres is authoritative for ordering across nodes; the drain is an insert that is a no-op if the (node, sequence) pair is already there, so replaying the queue twice is harmless.
When it fills: Stop accepting new work and report the worker as degraded. Dropping the oldest entries would silently lose exactly the results this store exists to keep; refusing new work is visible and reversible.
Drain proven end to end: never
Restore — from journal-offsite-s3
- Restore the newest snapshot to /var/lib/jarvisos/journal.db on VIN.
- Start the worker with drain-only mode so it pushes the backlog before accepting new work.
- Watch the drain to zero, then let it take work again.
Verified by: Queue depth reaches zero and the same number of rows appears in Postgres. Re-running the drain must change nothing, which is the property the conflict rule promises.
No drill on record. Until one exists, the restore above is a hypothesis.
- The reason this store exists is a finding on jarvisos-postgres: without it, VIN writes across the home uplink and stops when the house does.
- Home1 is gone: The primary is on this side. Reads and writes continue.
- VIN (the VPS) is gone: No copy of this data is reachable from this side of the break.
- Home internet is down: No copy of this data is reachable from this side of the break.
- The mesh is partitioned: No copy of this data is reachable from this side of the break.
- The NAS is gone: The primary is on this side. Reads and writes continue.
JarvisOS sessions & queue (Redis) estate-critical redis
redis · No signalSession state for the SSO chokepoint and the short-lived job queue. Losing it logs everyone out and drops in-flight jobs; it does not lose anything that was ever committed.
- Written by
- single writer — one primary, promotion is a separate act, primary on home1
- Recovery point — anywhere
- none today
- Recovery point — losing the site
- none today
- Copies
- 1 today, 1 by design, across fd-home-rack
- Last restore drill
- never
- Home uplink
- writes cross it; no off-site copy crosses it
Rebuilt, not restored
Start an empty Redis. Every user re-authenticates against Google on their next request; the job queue refills from the tasks table in jarvisos-postgres, which is authoritative for anything that had actually been accepted.
Costs: Everyone is logged out at once, and any job accepted but not yet started is re-derived from Postgres rather than resumed. Nothing committed is lost.
- The fix for the uplink dependency is not to replicate this store — it is rebuildable, so replicating it buys little. It is to move it: a Redis on VIN, with home1 pointing at it, puts the session store on the same node as the auth service that needs it and leaves nothing crossing the uplink on the login path. That is a placement change, tracked as its own task rather than smuggled in here.
- Home1 is gone: Start an empty Redis. Every user re-authenticates against Google on their next request; the job queue refills from the tasks table in jarvisos-postgres, which is authoritative for anything that had actually been accepted.
- VIN (the VPS) is gone: The primary is on this side. Reads and writes continue.
- Home internet is down: The primary is on this side. Reads and writes continue.
- The mesh is partitioned: The primary is on this side. Reads and writes continue.
- The NAS is gone: The primary is on this side. Reads and writes continue.
Coolify's own Postgres fleet-fatal postgres
not in the inventoryEvery application, server, destination, environment variable and deployment history Coolify holds. Losing it does not stop what is already running — it stops anything from being deployed, redeployed, restarted or rolled back, including the deploy that would replace whatever just failed.
Not watched: It runs inside Coolify's compose stack on home1 and is not declared in the inventory, so nothing here probes it. Coolify is the only thing that knows whether it is healthy.
- Written by
- single writer — one primary, promotion is a separate act, primary on home1
- Recovery point — anywhere
- 1d today · promised 1d
- Recovery point — losing the site
- none today (1d by design) · promised 1d
- Copies
- 2 today, 4 by design, across fd-home-rack, fd-offsite
- Last restore drill
- never
- Home uplink
- writes do not cross it; no off-site copy crosses it
Copies
| Copy | Kind | Where | Domain | Path | Behind by | Use |
|---|---|---|---|---|---|---|
| coolify-dump-local | logical dump | home1 | fd-home-rack | home-lan | 1d | restorable unencrypted |
| coolify-dump-nas planned | logical dump | nas-backups | fd-home-rack | home-lan | 1d | restorable |
| coolify-dump-offsite planned | logical dump | gwscli-s3-offsite | fd-offsite off-domain | home-egress via home uplink | 1d | restorable |
Restore — from coolify-dump-nas
- Install the same Coolify version the dump came from. A newer one will migrate the schema on boot and the rollback stops existing.
- Stop the Coolify stack, drop and recreate its database, `pg_restore` the dump.
- Start Coolify and re-enter the credentials it does not hold in the database.
- Reconcile against the estate: `scripts/jarvisos-estate.mjs reconcile` must match the register before anything is deployed.
Verified by: Coolify lists the same applications and servers as the disposition register captured, and one throwaway redeploy succeeds.
No drill on record. Until one exists, the restore above is a hypothesis.
- This is the store the estate-disposition register calls its single lifecycle point: while home1 is down, nothing in the estate can be deployed. See docs/ESTATE-DISPOSITION.md.
- The version pinning in the restore steps is not pedantry. Coolify migrates its own schema on boot, so a dump taken before an upgrade cannot be restored into the version that follows it.
- Home1 is gone: No copy of this data is reachable from this side of the break.
- VIN (the VPS) is gone: The primary is on this side. Reads and writes continue.
- Home internet is down: The primary is on this side. Reads and writes continue.
- The mesh is partitioned: The primary is on this side. Reads and writes continue.
- The NAS is gone: The primary is on this side. Reads and writes continue.
Supabase (edge database) estate-critical supabase-postgres
not in the inventoryThe user-facing edge database: auth, row-level security and the tables the public apps read through PostgREST. It is where a browser writes; JarvisOS Postgres is where the estate's own record lives.
Not watched: Vendor-held. There is no host of ours to probe and no entity to declare; what we can see is what the API answers.
- Written by
- vendor-managed — the provider decides, and does not say how, held by Supabase (eu-central-1)
- Recovery point — anywhere
- 1d today · promised 1d
- Recovery point — losing the site
- 1d today · promised 1d
- Copies
- 2 today, 3 by design, across fd-home-rack, fd-offsite, vendor-supabase
- Last restore drill
- never
- Home uplink
- writes do not cross it; every off-site copy crosses it
Copies
| Copy | Kind | Where | Domain | Path | Behind by | Use |
|---|---|---|---|---|---|---|
| supabase-dump-nas | logical dump | nas-backups | fd-home-rack off-domain | vendor-api via home uplink | 1d | restorable |
| supabase-dump-offsite planned | logical dump | gwscli-s3-offsite | fd-offsite off-domain | home-egress via home uplink | 1d | restorable |
Restore — from supabase-dump-nas
- Decide the target first: back into Supabase (a new project, then repoint the app) or into jarvisos-postgres (the exit plan, under time pressure — do not choose this during an incident unless Supabase itself is the incident).
- Create the target database and the roles the dump references. `anon` and `authenticated` do not exist outside Supabase and must be created by hand.
- pg_restore the dump. Expect the auth schema to fail against a plain Postgres; that is the part the exit plan calls out.
- Repoint the app's connection string and rotate the anon and service keys.
- Verify (below) before announcing.
Verified by: One row inserted through the app's own path, read back through PostgREST, and one row that RLS should hide staying hidden for an anonymous key.
No drill on record. Until one exists, the restore above is a hypothesis.
Supabase holds this
They decide: Failover, point-in-time recovery, the Postgres version, the maintenance window and how long any of that takes. None of it is visible from here and none of it can be tested from here.
Way off it: The schema is plain Postgres and every table used by the estate is reachable through a logical dump. Moving to jarvisos-postgres means: run both, dual-write from the app for one release, cut reads over, then stop writing to Supabase. What does not move for free is auth — GoTrue's user table and the RLS policies would have to be replaced by jarvisos-auth, which is the reason this is a plan and not a scheduled migration.
- Supabase stays where user-facing auth and realtime live, because replacing GoTrue is a project rather than a migration. What changes here is that the estate stops relying on the vendor being the only place the data exists: a nightly logical dump is pulled to the NAS and pushed off-site, under our own encryption, so an account or billing problem is an inconvenience rather than a data loss.
- Nothing in this register holds a Supabase credential. The dump job reads its connection string from /etc/jarvisos/config.env, which is not in this repository.
- Home1 is gone: The primary is on this side. Reads and writes continue.
- VIN (the VPS) is gone: The primary is on this side. Reads and writes continue.
- Home internet is down: Only supabase-dump-nas is reachable; recovery here means restoring it.
- The mesh is partitioned: The primary is on this side. Reads and writes continue.
- The NAS is gone: The primary is on this side. Reads and writes continue.
Migrations and their rollbacks
2/3 reversibleA migration is a write to every copy. Expand-contract survives a replica applying the old shape and a rollback that lands on the previous release; anything else has to say what it can be undone from and what that costs.
Add an owner column to tasks expand-contract reversible
jarvisos-postgres- Expand: ADD COLUMN owner text NULL. Nothing reads it yet, and a nullable column is invisible to the running release.
- Backfill in batches of 1000 with a sleep between, so replication lag stays under the 30s the recovery point assumes.
- Deploy the release that writes and reads the column.
- Contract, one release later: SET NOT NULL once the backfill is proven complete.
Verified by: SELECT count(*) FROM tasks WHERE owner IS NULL returns zero before the contract step, and the previous release still boots against the expanded schema.
Rollback — inverse-migration
- DROP COLUMN owner
Costs at most: nothing · last executed: 2026-08-03
The shape of every migration to this store: each step is safe on its own, the old release keeps running against the new schema, and no step needs the replica to have caught up.
Drop the legacy heartbeats table destructive not reversible
jarvisos-postgres- Confirm the newest pg-base-nas snapshot is under 6h old and that pg-wal-nas is current.
- Drain jarvisos-vin-journal to zero and hold the worker. A queue can be holding rows written by a release that predates this change, and they still have to land.
- RENAME the table to heartbeats_legacy_20260901 and leave it for one full retention period.
- DROP it only after that period, and only if nothing has asked for it.
Verified by: No error in the control-plane log referencing the table for a full retention period after the rename.
Rollback — restore from pg-wal-nas
- Point-in-time restore to the minute before the drop, into a scratch instance.
- pg_dump the single table out of the scratch instance and load it back into the live database.
Costs at most: 5m of writes · last executed: never
The rename-then-drop is what makes an irreversible change reversible for a retention period. The restore path exists for the case where someone skips the wait.
Journal schema v2 — add a node sequence expand-contract reversible
jarvisos-vin-journal- Expand: ADD COLUMN node_seq integer NULL and a unique index on (node_id, node_seq) WHERE node_seq IS NOT NULL.
- New writes carry the sequence; queued rows written by the previous release do not, and drain unchanged.
- Contract only once the queue has drained to zero at least once under the new release.
Verified by: A disconnect-and-drain with rows written by both releases in the queue, ending at zero depth with no duplicate rows in Postgres.
Rollback — inverse-migration
- DROP INDEX, DROP COLUMN node_seq
Costs at most: nothing · last executed: never
A local-first store makes the expand-contract rule non-negotiable: at any moment the queue may hold rows written by a release that is no longer installed, and they still have to drain.
Accepted risks
Decisions on record, each with a review date-
Accepted risk: Fewer independent copies than policy requires. jarvisos-vin-journalJarvisOS VIN journal exists in 1 place(s) today; policy wants 3. Planned: journal-offsite-s3.Accepted by homelab-operator, review 2027-02-01: This is a bounded queue, not a system of record. Anything in it is either drained into Postgres within minutes — where the three-copy rule does apply — or it is still in flight. A third copy of a queue protects nothing that Postgres is not already protecting, and it would cost a second place for unfinished work to leak from.
Notes
Structural facts and design not yet adopted-
Note: A store has no inventory entity, so nothing here can tell whether it is up. jarvisos-vin-journalJarvisOS VIN journal has no inventory entity, so nothing here can tell whether it is up: Planned. Nothing runs on VIN to declare yet, so the inventory has no entity for it and the health engine cannot see it.
-
Note: The design meets its objectives only because of copies that are not running yet. jarvisos-vin-journalJarvisOS VIN journal reaches 15m / site 15m only once journal-offsite-s3 is running. Today it is none / site none.
-
Note: A store has no inventory entity, so nothing here can tell whether it is up. coolify-stateCoolify's own Postgres has no inventory entity, so nothing here can tell whether it is up: It runs inside Coolify's compose stack on home1 and is not declared in the inventory, so nothing here probes it. Coolify is the only thing that knows whether it is healthy.
-
Note: The design meets its objectives only because of copies that are not running yet. coolify-stateCoolify's own Postgres reaches 1d / site 1d only once coolify-dump-nas, coolify-dump-offsite are running. Today it is 1d / site none.
-
Note: A store has no inventory entity, so nothing here can tell whether it is up. supabase-edgeSupabase (edge database) has no inventory entity, so nothing here can tell whether it is up: Vendor-held. There is no host of ours to probe and no entity to declare; what we can see is what the API answers.
-
Note: The design meets its objectives only because of copies that are not running yet. supabase-edgeSupabase (edge database) reaches 1d / site 1d only once supabase-dump-offsite is running. Today it is 1d / site 1d.
How to read this page
- Two recovery points are derived for every durable store, not one. The first is the best copy anywhere: it survives a dead disk in home1. The second is the best copy outside the primary's failure domain: it is the only one that survives the room. A WAL archive on the NAS is excellent at the first and worth nothing for the second.
- Off-site protection must not share one uplink. If every copy that leaves the estate is pushed over the home internet connection, then a home internet outage stops all off-site protection advancing while the primary keeps accepting writes — and nothing looks broken until the site is gone. The fix is a second off-site path that starts somewhere else, which is why the VPS pushes its own copy.
- This estate has two compute domains. A majority needs three, so nothing here promotes itself: every promotion is a human act with a fencing step, and automatic promotion of durable state is a finding rather than a feature.
- A restore nobody has run is a hypothesis. Drill evidence carries a date, an outcome and a measured duration, and it is the measurement that is checked against the RTO.
- Findings describe the estate as it runs. Where the design closes one, that appears as a note rather than as a clean bill of health.
Source: config/datastores.json · machine-readable at /api/v1/data ·
narrative in docs/DATA-RESILIENCE.md.