Scenario 07 — Point-in-time rollback
You need a specific moment, not “yesterday.” A bad deploy at 14:30 quietly corrupted data over the next hour. You want the volume exactly as it was at 14:00, just before things went wrong, and you don’t want to scroll through Snapshot CRs guessing which one that was.
Use source.fromPolicy with asOf. It resolves through the SnapshotPolicy’s identity, so it still works if the relevant Snapshot CR has aged out of the catalog, and it picks the newest snapshot at or before an instant. As always, restore into a side-by-side PVC and verify before cutting over.
Step 1 — Choose the instant
Section titled “Step 1 — Choose the instant”You don’t list snapshots. You name the time. asOf takes an RFC3339 timestamp and resolves to the newest snapshot at or before it. If you’d rather count backwards, use offset instead: 0 is the latest, 1 is the previous one, and so on.
Step 2 — Restore into a clone and verify
Section titled “Step 2 — Restore into a clone and verify”The bundle restores into a fresh postgres-data-1400 PVC. The live volume is untouched.
fromPolicy defaults to onMissingSnapshot: Continue, which is the deploy-or-restore behavior. A deliberate rollback sets it to Fail instead, so an instant with no snapshot is a loud error rather than a silently empty volume.
# Scenario 07 — Point-in-time rollback (roll an app back to a known-good moment)## A bad deploy at 14:30 corrupted the data over the next hour. You don't want# "yesterday" and you don't want to hunt for the exact Snapshot CR — you want# "whatever the data looked like at 14:00, just before it went wrong."## `source.fromPolicy` resolves through the SnapshotPolicy's IDENTITY (not a specific# Snapshot CR), so it works even if that Backup has aged out of the catalog. `asOf`# picks the newest snapshot AT OR BEFORE an instant; `offset` picks by position# (0 = latest, 1 = previous, ...). Restore into a NEW PVC and compare before cutting# over — never overwrite the live volume on the first attempt.## Field shapes verified against crates/api: source.fromPolicy =# { name, namespace?, asOf?, offset? }; target.pvc creates a new PVC.---apiVersion: kopiur.home-operations.com/v1alpha1kind: Restoremetadata: name: postgres-rollback-1400 namespace: billingspec: source: fromPolicy: name: postgres-data # the SnapshotPolicy protecting the live volume asOf: 2026-05-20T14:00:00Z # the last good moment, just before the bad deploy # offset: 1 # ...or by position instead of a timestamp target: pvc: name: postgres-data-1400 # a side-by-side clone — the live PVC is untouched storageClassName: fast-ssd capacity: 100Gi accessModes: - ReadWriteOnce policy: # fromPolicy DEFAULTS to Continue (deploy-or-restore). For a deliberate rollback # you want it to FAIL loudly if nothing matches that instant. onMissingSnapshot: Fail waitTimeout: 5m## Watch it, then verify against the clone before you cut over:# kubectl get restore postgres-rollback-1400 -n billing -w# # spin a throwaway psql pointed at postgres-data-1400, confirm the data is right## Cut over once you're satisfied: scale the app down, then either repoint it at the# clone PVC, or do an in-place mirror restore into the live PVC (example 15):## spec:# source: { fromPolicy: { name: postgres-data, asOf: 2026-05-20T14:00:00Z } }# target: { pvcRef: { name: postgres-data } } # the EXISTING live PVC# options: { enableFileDeletion: true } # exact mirror of the snapshot$ kubectl get restore postgres-rollback-1400 -n billing -wNAME PHASE AGEpostgres-rollback-1400 Resolving 2spostgres-rollback-1400 Restoring 9spostgres-rollback-1400 Completed 44sPoint a throwaway client at the clone PVC and confirm the data is the moment you wanted.
Step 3 — Cut over
Section titled “Step 3 — Cut over”Once you trust the clone, scale the app down. Then either repoint it at the clone, or do an in-place mirror restore into the live PVC. That means target.pvcRef plus options.enableFileDeletion: true, which makes the live volume an exact mirror of the chosen instant. See example 15. The in-place form is shown commented at the bottom of the bundle.
See also
Section titled “See also”- Restores → point-in-time: the
asOfandoffsetreference. - Example 14: point-in-time / offset restore and example 15: in-place mirror.
- Scenario 02, recover lost data: the same safe clone-and-verify habit for a known
SnapshotCR.