Sandboxes
Checkpoints & Rollback
Capture sandbox state, restore quickly, and fork prepared runtimes for parallel work.
A checkpoint captures a sandbox's full state so you can restore it later or fork it into parallel copies.
Use checkpoints when setup is expensive and you want repeatable branching.
Snapshot and restore
import { Isorun } from 'isorun'
const isorun = new Isorun()
const sandbox = await isorun.create({ image: 'python:3.12-slim' })
await sandbox.exec('pip install numpy pandas')
const snap = await sandbox.snapshot()
await sandbox.destroy()
// Later, anywhere in the same region:
const restored = await isorun.restore(snap.id)
try {
const r = await restored.exec("python3 -c 'import numpy; print(numpy.__version__)'")
console.log(r.stdout.trim())
} finally {
await restored.destroy()
}Fork for parallel hypotheses
Prepare once, then fork multiple children for concurrent experiments.
const parent = await isorun.create({ image: 'python:3.12-slim' })
await parent.exec('pip install transformers torch')
const children = await parent.fork(5)
try {
await Promise.all(
children.map((child, i) => child.exec(`python3 evaluate.py --variant=${i}`))
)
} finally {
await Promise.all(children.map((c) => c.destroy()))
await parent.destroy()
}What carries over
- Filesystem state at fork/snapshot time.
- Loaded runtime state (so setup usually does not need to re-run).
- Environment configuration applied before checkpoint/fork.
What resets
- Active outbound network sessions.
- In-flight operations at the time of checkpoint/fork.
- Per-sandbox runtime control channel.
Roll back to a snapshot
const sandbox = await isorun.create({ image: 'python:3.12-slim' })
try {
await sandbox.exec("echo 'state-ok' > /tmp/state.txt")
const snap = await sandbox.snapshot()
const failed = await sandbox.exec('rm /tmp/state.txt && exit 1')
if (failed.exitCode !== 0) {
await sandbox.destroy()
const rolled = await isorun.restore(snap.id)
const r = await rolled.exec('cat /tmp/state.txt')
console.log(r.stdout.trim())
await rolled.destroy()
}
} finally {
// sandbox may already be destroyed above; destroy() throws on a destroyed
// sandbox, so guard for production code.
}destroy() throws if the sandbox is already destroyed. When a code path may destroy a sandbox before the finally block runs, guard the cleanup call.
Operational checklist
- Store snapshot IDs alongside job metadata.
- Destroy restored/forked children in
finallypaths. - Set explicit
exec()timeouts in child runs. - Call
isorun.deleteSnapshot(id)when a snapshot is no longer needed.
Next steps
- Lifecycle and hibernation, pause a single sandbox instead of snapshotting it.
- TypeScript SDK,
snapshot(),restore(), andfork()reference.