Isorun Docs
Sandboxes

Lifecycle & Hibernation

Create, run, hibernate, resume, and destroy a sandbox, and the cost model behind each transition.

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

This page walks each transition and the cost model behind it.

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

   └─ destroy() ─► destroyed

Create a sandbox

It boots a microVM with its own kernel. Defaults: 1 vCPU, 1 GiB RAM, 4 GiB writable scratch disk that grows on write.

TypeScript
import { Isorun } from 'isorun'

const isorun = new Isorun()
const sandbox = await isorun.create({ image: 'python:3.12-slim' })
console.log(sandbox.id)        // run<...>
console.log(sandbox.createMs)  // server-side create duration in ms

Wrap the work in try { … } finally { destroy() } so the sandbox is always freed:

TypeScript
const sandbox = await isorun.create({ image: 'python:3.12-slim' })
try {
  await sandbox.exec("python3 -c 'print(42)'")
} finally {
  await sandbox.destroy()
}

Hibernate a sandbox

Hibernation pauses the sandbox, persists its state, and releases active runtime resources. The runID stays valid, so the user sees 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.

TypeScript
const sandbox = await isorun.create({ image: 'python:3.12-slim' })
await sandbox.exec('pip install numpy pandas')  // setup work

// User closes their laptop. Hibernate the workspace.
await sandbox.hibernate()

// Hours later, the user comes back…
await sandbox.resume()

// 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.
await sandbox.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 network interface with a new guest IP. Listen sockets and the kernel's TCP stack survive cleanly.

The VM gets a new guest IP on resume, so any ESTABLISHED outbound TCP connection from before hibernation is reset. Code that holds a long-lived connection (a database pool, a streaming HTTP client) must reconnect after resume().

Resume a sandbox

Resume restores a hibernated sandbox. 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 a sandbox

Destroy frees the sandbox permanently, including any hibernation snapshot on disk. It returns measured resource usage, these are the numbers you're billed on.

TypeScript
const stats = await sandbox.destroy()
console.log(stats.cpuMs)          // CPU time used
console.log(stats.memPeakBytes)   // peak RSS
console.log(stats.uptimeMs)       // wall-clock from create to destroy
console.log(stats.costCents)      // exact billed amount in cents

Auto-destroy timeout

Every sandbox has an idle timeout (default 300 seconds, configurable per-create via timeoutSec). When the timer fires, the sandbox is destroyed. Use sandbox.setTimeout(seconds) to extend it during a long-running workflow, pass 0 to disable.

Tip

Reach for hibernation when you want the workspace to persist but the VM resources released. The user-facing experience is "always on"; the runner-facing cost is "only when you're actively running."

Next steps

On this page