Skip to content
docs
Arxo ↗

Rollback

For LLMs9 sections

Return a deployment to the last accepted state — runtime binary plus pinned world — quickly, in a defined order, with explicit success criteria and known limits.

Component law CLI + serve deployment, tool 0.1.1. Scenario: the new state (after an upgrade switch per Upgrades and compatibility) is rejected during the observation window; the prior bundle, lock, and binary were kept on the host. All identifiers below are synthetic created-examples.

  • The prior state intact on the host: prior .arxo bundle + hashes, prior law.lock, prior law binary path (or reinstallable pinned archive + .sha256).
  • The rejected state’s identity recorded: new bundle name, new pin (GET /v1/world output), new law version --json.
  • The decision journal preserved. One journal directory is shared across generations: every record carries its world’s pin, so entries from the prior window and the rejected window normally coexist in the same directory. Windows are distinguished by recorded pin and decision id, not by separate directories.
  1. Declare the rollback: record which state is rejected and why; freeze further switches (operator-policy-example: page the change owner — created-example process).
  2. Stop intake on the rejected world: disable the ingress route, then stop law serve and confirm the PID is gone (no graceful drain exists — in-flight calls die; only completed decisions have records). Fencing the port alone does not stop writers.
  3. Switch order — data-plane first, then control-plane (operator-policy-example order): (a) restore the prior world directory from the labeled backup set (--world accepts a directory or a profile.json, never a .arxo bundle directly), then repoint the --world symlink to it; (b) if the runtime binary also moved, restore the prior binary path — runtime and world roll back together, never the world alone under a rejected binary.
  4. Verify integrity of the selected artifacts and configuration BEFORE starting anything (real): law inspect <prior-bundle> --verify --trust <key>. Do not rely on the runtime to refuse damaged artifacts implicitly — a rollback procedure must not start a state it has not checked.
  5. Start the chosen runtime + world pair with external traffic still fenced off. Step 2 stopped the process, so no running watcher can warm the prior world for you — this recipe always restarts; a hot rollback that relies on --watch-world without stopping would be a different procedure.
  6. Check readiness and identity on the fenced instance, in this order: GET /readyz is 200, then GET /v1/world shows the prior pin. Re-run acceptance on the restored state (real): law test over the prior project, law eval over a saved calculation, and law replay-record --world <prior> --journal <dir> --decision <id> for the prior window’s decision ids. Each record is pin-checked against the loaded world; a record from another generation reports PIN_MISMATCH instead of replaying silently. Finish with one synthetic control query through POST /v1/ask (real endpoint) and confirm the expected document.
  7. Open ingress only after step 6 is fully green.
  8. Fate of the rejected window’s cases and records: keep the journal whole — do not delete rejected-window records and do not rewrite history (the journal has no rewrite command — implementation limit). Decisions served during the rejected window stay recorded with the rejected pin; re-ask any affected cases against the restored world explicitly (new journal entries, new decisions). Select records by recorded pin and decision id; there is no supported “split this journal into two directories” procedure.
  9. Mutable-data compatibility: if host-side systems consumed rejected decisions (tickets, payments, notifications), reconcile them case-by-case from the preserved rejected-window records; the tool cannot retract served decisions (implementation limit, not a missing flag).
  • GET /v1/world reports the prior pin; /readyz is 200.
  • law test, law eval, and law replay-record exit 0 on the restored state.
  • The journal preserved whole; prior-window and rejected-window records remain distinguishable by recorded pin.
  • Pin check: served pin equals the recorded prior pin, not merely “an old pin”.
  • Replay check: prior-window journal replays cleanly (resultHash/outcomeHash match per entry).
  • Diff check: law case diff between a pre-upgrade saved evaluation and a post-rollback fresh ask of the same case is empty.
  • Intake check: one synthetic ask through POST /v1/ask (real endpoint) returns the expected document before real traffic resumes.
  • /readyz not 200 after the step 5 restart: the prior world did not warm — check the symlink target, bundle readability, and server stderr; serve was possibly started against a pruned path.
  • law replay-record mismatch on the prior journal: the “prior” world is not byte-identical to the accepted one (re-pack drift or lock edit); restore from the labeled backup set (Backup and restore).
  • Prior binary missing: reinstall from the pinned archive + .sha256 (per Install and trust artifacts) rather than downgrading through a package manager’s “latest”.
  • Records from several pins in one journal: normal after any --watch-world switch, not a fencing failure. Select by recorded pin and replay each record against the world that matches its pin.
  • Supported: world + runtime rollback via kept bundles, locks, and binaries; per-entry replay verification.
  • Implementation limits: no journal merge/rewrite/retract commands; no automatic rollback trigger — the switch is always an operator act.
  • Rollback limits: rollback restores the answering state, not the consequences of rejected answers; downstream effects need case-by-case reconciliation. “Safe rollback” in this article means only “the defined order was followed and all checks are green”.

File the rollback report (rejected pin, cause, affected decisions, reconciliation list) and re-plan the upgrade as a new change; do not re-attempt the same switch without a new review.

Documentation for Arxo. Writings — blog.arxo.io.

Anonymous visit counts on stats.arxo.io, no cookies.