Skip to content

Lifecycle & Hibernation

A sandbox moves through five states. The transitions between them are the only operations that cost money: an idle hibernated sandbox costs nothing on the runner side.

create() exec()
┌──────────────► running ◄────────┐
│ │ │
│ hibernate() │
│ ▼ │
│ hibernated │
│ │ │
│ resume() │
│ ▼ │
│ running ──────────┘
└─ destroy() ─► destroyed

Create

Boots a Firecracker microVM in 27 ms on bare metal (cold start, no warm pool). The VM has its own kernel, 1 GiB RAM, and a 3 GiB scratch disk that grows on write.

from isorun import Sandbox
sb = Sandbox("python:3.12")
sb.create()
print(sb.id) # run<16-hex>
print(sb.info.create_ms) # 27

The recommended pattern is the context manager — it auto-destroys on exit even if your code throws:

with Sandbox("python:3.12") as sb:
sb.exec("python3 -c 'print(42)'")
# sandbox is destroyed here

Hibernate

Pause the VM, snapshot it to local disk, and free its FC process / TAP device / cgroup. The runID stays valid; the user perceives a paused workspace they can come back to. The runner only spends resources when the sandbox is actively running, so a hibernated sandbox is essentially free.

sb = Sandbox("python:3.12")
sb.create()
sb.exec("pip install numpy pandas") # 30s of setup work
# User closes their laptop. We hibernate the workspace.
sb.hibernate() # ~470 ms
# Hours later, the user comes back…
sb.resume() # ~21 ms — faster than a cold create
# State is identical to what it was at hibernate time:
# the pip-installed packages are still there, the cwd is preserved,
# and any background processes the user started are still running.
sb.exec("python3 -c 'import numpy; print(numpy.__version__)'")

What survives a hibernate/resume cycle:

  • Filesystem state. Anything you wrote to the scratch disk is intact.
  • Memory state. Every page the VM had loaded is preserved — including in-memory caches, JIT-compiled bytecode, and database working sets.
  • Process state. Background processes the user started before hibernation are still running at the same PIDs after resume. A long-running node server.js, a jupyter notebook kernel, an SSH agent — they all survive.
  • Open file descriptors and listen sockets. The VM’s network stack is re-attached to a fresh TAP device with a new guest IP, so any ESTABLISHED TCP connections from before hibernation will be reset. Listen sockets and the kernel’s TCP stack survive cleanly.

Resume

Restores a hibernated sandbox in 21 msfaster than a fresh create, because the resume path skips the golden-snapshot pre-warm overhead. The user perceives a workspace that’s “always there” without paying for it during idle periods.

The same runID is reused across hibernate/resume cycles, so client code that holds a reference to a sandbox doesn’t need to track a new identity.

Destroy

Frees the sandbox permanently, including any hibernation snapshot on disk. Returns measured resource usage — these are the numbers you’re billed on.

stats = sb.destroy()
print(stats.cpu_ms) # 1247
print(stats.mem_peak_bytes) # 84_672_512
print(stats.disk_used_bytes) # 12_288
print(stats.uptime_ms) # 8_421

Auto-destroy timeout

Every sandbox has an idle timeout (default 5 minutes, configurable per-create with sandbox_timeout). When the timer fires, the sandbox is destroyed. Set sandbox_timeout=-1 to disable the timer entirely for long-running workloads.

Hibernation is the right answer when you want the workspace to persist but the VM resources released. The user-facing UX is “always on”; the runner-facing cost is “only when you’re actively running.”

What each transition costs

TransitionTime on bare metalWhat’s happening
create()27 msFC restore from golden snapshot, vsock init, TAP attach
exec() (separate calls)~7 msvsock dial, agent fork, command run
exec() inside a shell()~0.1 msno fork — pipes into the long-lived bash
fork() (per child after the first)~16 mshardlink mem.snap, reflink scratch, FC restore
hibernate()469 msFC snapshot/create + reflink scratch + cleanup
resume()21 msFC restore + vsock init
destroy()9 mskill FC process, free TAP/cgroup, cleanup runDir

Per-second billing means an idle sandbox costs about $0.000011/sec running, and zero while hibernated.