From 876bddb19283d737f897de2db5ed4034f2bfba13 Mon Sep 17 00:00:00 2001 From: yaowenc2 Date: Sun, 30 Aug 2026 18:36:28 -0700 Subject: [PATCH 1/3] fix: provider-honest `compute suspend` help copy "RAM snapshot" was Fly-era wording and is false on the insta-compute provider, where suspend releases the microVM entirely: only the code disk and /data volume persist, and wake boots fresh in about a second. Co-Authored-By: Claude Fable 5 --- src/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/index.ts b/src/index.ts index df186f5..a10e752 100644 --- a/src/index.ts +++ b/src/index.ts @@ -227,7 +227,7 @@ compute.command('start [service]').description('Bring a compute service online ( .option('--json').option('--branch ', 'branch (default: current)').action(guard((service, o) => computeCmd.computeStart(service, o))) compute.command('stop [service]').description('Take a compute service offline; traffic will NOT wake it until `start`') .option('--json').option('--branch ', 'branch (default: current)').action(guard((service, o) => computeCmd.computeStop(service, o))) -compute.command('suspend [service]').description('Suspend a compute service (RAM snapshot); stays down until `start`') +compute.command('suspend [service]').description('Suspend a compute service (scales to zero; disk/volume state persists, in-memory state does not); stays down until `start`') .option('--json').option('--branch ', 'branch (default: current)').action(guard((service, o) => computeCmd.computeSuspend(service, o))) compute.command('restart [service]').description("Restart a compute service by re-running the image it already runs against a freshly resolved env bundle — this is how a changed secret or binding reaches a running machine (env is baked into the machine at deploy time), and how a machine that is up but wedged gets cycled (`start` no-ops on one that is already started). No new image, no new spec. The service must be running: a stopped or suspended one comes back with `insta compute start`. All plans; gated: deploy — it lands configuration the same way a deploy does, so a policy denying deploys denies this too (`start`/`stop` stay ungated, and cycle a wedged machine without one). A service whose app fails to answer on its port coming back up reports that failure, and the machines are rolled back, best-effort, to the config they were serving") .option('--json').option('--branch ', 'branch (default: current)').action(guard((service, o) => computeCmd.computeRestart(service, o))) From cf823f700ffbc994d5827d591a1b7b3b63bc0a25 Mon Sep 17 00:00:00 2001 From: yaowenc2 Date: Sun, 30 Aug 2026 18:56:05 -0700 Subject: [PATCH 2/3] fix: make suspend copy honest on both compute planes Review round 1: legacy Fly-backed services still get a true RAM-snapshot suspend, so "in-memory state does not persist" was unconditional in the wrong direction; and volume-bearing services cannot be suspended at all, so "volume state persists" pointed at an unreachable case. "Releases the machine" also avoids overloading "scales to zero", which this help output uses for auto-wake behavior. Co-Authored-By: Claude Fable 5 --- src/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/index.ts b/src/index.ts index a10e752..e3e93cd 100644 --- a/src/index.ts +++ b/src/index.ts @@ -227,7 +227,7 @@ compute.command('start [service]').description('Bring a compute service online ( .option('--json').option('--branch ', 'branch (default: current)').action(guard((service, o) => computeCmd.computeStart(service, o))) compute.command('stop [service]').description('Take a compute service offline; traffic will NOT wake it until `start`') .option('--json').option('--branch ', 'branch (default: current)').action(guard((service, o) => computeCmd.computeStop(service, o))) -compute.command('suspend [service]').description('Suspend a compute service (scales to zero; disk/volume state persists, in-memory state does not); stays down until `start`') +compute.command('suspend [service]').description('Suspend a compute service (releases the machine; disk state persists — do not rely on in-memory state surviving); stays down until `start`') .option('--json').option('--branch ', 'branch (default: current)').action(guard((service, o) => computeCmd.computeSuspend(service, o))) compute.command('restart [service]').description("Restart a compute service by re-running the image it already runs against a freshly resolved env bundle — this is how a changed secret or binding reaches a running machine (env is baked into the machine at deploy time), and how a machine that is up but wedged gets cycled (`start` no-ops on one that is already started). No new image, no new spec. The service must be running: a stopped or suspended one comes back with `insta compute start`. All plans; gated: deploy — it lands configuration the same way a deploy does, so a policy denying deploys denies this too (`start`/`stop` stay ungated, and cycle a wedged machine without one). A service whose app fails to answer on its port coming back up reports that failure, and the machines are rolled back, best-effort, to the config they were serving") .option('--json').option('--branch ', 'branch (default: current)').action(guard((service, o) => computeCmd.computeRestart(service, o))) From 8af2795c7e73ac1b736672b450bef6b024fd86a4 Mon Sep 17 00:00:00 2001 From: yaowenc2 Date: Sun, 30 Aug 2026 21:22:02 -0700 Subject: [PATCH 3/3] fix: drop the false disk-durability promise from suspend copy Review round 2 Critical: "disk state persists" is false on every insta-compute suspend. The platform refuses suspend on volume-bearing services (services.ts:1305-1307), so the verb only reaches volumeless ones; there the VM's writable rootfs is a CoW clone deleted on release (warm.go:1157-1159, k8s_warm.go:450-451) and finishSuspend flushes only an img /data volume (k8s.go:843-854). The copy now promises nothing about durability, states the plane-invariant facts, and points volume-bearing services at `stop`. Co-Authored-By: Claude Fable 5 --- src/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/index.ts b/src/index.ts index e3e93cd..3f210d4 100644 --- a/src/index.ts +++ b/src/index.ts @@ -227,7 +227,7 @@ compute.command('start [service]').description('Bring a compute service online ( .option('--json').option('--branch ', 'branch (default: current)').action(guard((service, o) => computeCmd.computeStart(service, o))) compute.command('stop [service]').description('Take a compute service offline; traffic will NOT wake it until `start`') .option('--json').option('--branch ', 'branch (default: current)').action(guard((service, o) => computeCmd.computeStop(service, o))) -compute.command('suspend [service]').description('Suspend a compute service (releases the machine; disk state persists — do not rely on in-memory state surviving); stays down until `start`') +compute.command('suspend [service]').description('Suspend a compute service: takes the machine down until `start` — do not rely on in-memory or on-disk state surviving (a service with a /data volume cannot be suspended; use `stop`)') .option('--json').option('--branch ', 'branch (default: current)').action(guard((service, o) => computeCmd.computeSuspend(service, o))) compute.command('restart [service]').description("Restart a compute service by re-running the image it already runs against a freshly resolved env bundle — this is how a changed secret or binding reaches a running machine (env is baked into the machine at deploy time), and how a machine that is up but wedged gets cycled (`start` no-ops on one that is already started). No new image, no new spec. The service must be running: a stopped or suspended one comes back with `insta compute start`. All plans; gated: deploy — it lands configuration the same way a deploy does, so a policy denying deploys denies this too (`start`/`stop` stay ungated, and cycle a wedged machine without one). A service whose app fails to answer on its port coming back up reports that failure, and the machines are rolled back, best-effort, to the config they were serving") .option('--json').option('--branch ', 'branch (default: current)').action(guard((service, o) => computeCmd.computeRestart(service, o)))