inis.run

Session lifecycle

Templates, live vs paused, hot/warm/cold resume, checkpoints, and the timers that move a session along.

A session is one sandbox you create, use, pause, and destroy. Everything else — templates, checkpoints, fork, timers — is how you start it, save it, or copy it.

template ──► creating ──► live ⇄ paused (hot → warm → cold) ──► destroyed
                              │                │
                         checkpoint      wake on next op
                         save as template

Starting — templates

A template is where you start. Official ones (base, python, node, …) or one you published from an earlier session.

inis sessions create --template python
# or pin an exact build:
inis sessions create --template python@2026.07.10

The first boot from a template is a cold start — the environment is brought up fresh. After that, if you pause and come back, you are waking the same session (files, packages, and running-process state from when you left), not starting over from the template.

Start pathWhat you get
Template (official or yours)New session from a known baseline
Checkpoint → new sessionNew session branched from a save-point of an old one
Stateless run (inis run, /v1/sessions/exec)Same create → run → destroy, no ID to keep

See Concepts for when to keep a session vs run code and throw it away.

Live and paused

StateMeaningCompute
creatingComing up; not ready for exec yetBrief
liveRunning — exec, files, expose, PTY all workYes
pausedSaved and sleeping — no processes runningNo (storage only)
destroyed / endedGone; ended is history metadata onlyNo

Live → paused when you pause explicitly, when idle timeout fires, when max_lifetime_ms fires (auto-pause, not destroy — see Timers below), or when the last PTY client leaves (on_pty_detach: pause, the default).

Paused → live on any operation (exec, files, expose, processes) or SSH/PTY attach — wake-on-op. One exception, added deliberately: an expose call that is already satisfied (the port is exposed with exactly the settings asked for) answers from the existing route and leaves the session asleep, so a loop re-asserting the exposure it wants doesn't wake and bill every sleeping session on every pass. You rarely need to call resume yourself. Exception: a session paused by its own max_lifetime_ms firing cannot wake again — resume (explicit or automatic) is refused. That pause is permanent; see max_lifetime_ms in Timers below.

Destroyed when you delete it, when paused_ttl_ms fires, or when a detach policy / completion flag tears it down. A destroyed session's saved snapshot is deleted at the same time. If the session ended because the machine it ran on was lost, or that deletion fails, the snapshot is kept for 30 days after the session ended and then deleted. max_lifetime_ms only destroys as a fallback, if the auto-pause it triggers can't itself succeed (e.g. a wedged VM) — it never destroys a healthy session, it just permanently pauses it.

Resume speed — hot, warm, cold

A paused session is not one speed. The console and API expose snapshot_tier — how ready the session is to wake:

TierWhere it sitsWake feel
hotFast local copyInstant (tens of ms after a slot is ready)
warmCompressed local copyQuick (local decompress, typically ~1–2 s)
coldEuropean object storage onlySlower (download + restore, often several seconds)

The platform demotes dormant sessions over time (and under disk pressure): hot → warm → cold. Any successful wake promotes back toward hot and resets that clock. You do not pick the tier yourself — you see it on the session while it is paused.

Capacity in the console also talks about running (live) vs warm (paused, resumable). Same idea: warm quota is how many paused sessions you can hold.

Saving — pause vs checkpoint vs template

These sound alike. They are different jobs:

PauseCheckpointTemplate
JobStop paying compute; come back to this sessionSave-point you can roll back to or branch fromNamed starting environment for new sessions
Outlives the session?NoYes (until you delete it)Yes
Typical useAgent idle between tool callsClean baseline / rollback after untrusted code“Always start from this env”
# Pause this session (auto-wakes on next op)
inis sessions pause "$SID"

# Save-point on the same session
inis sessions checkpoint "$SID" --name clean
inis sessions restore "$SID" --checkpoint clean

# Publish a reusable start environment (see Templates)
# Console: Save as template — or create new sessions from a checkpoint

Fork is the parallel path: clone a live session into N children for eval / rollouts. Ephemeral — not a long-lived save. Details in Concepts.

Timers

Set at create (Sessions API / CLI flags). Omit for server defaults.

KnobEffect
idle_timeout_msAuto-pause after this much idle time while live
on_pty_detachpause (default), keep_live, or destroy when the last terminal leaves (PTY only)
paused_ttl_msAuto-destroy after sitting paused this long (0 / omit = default; negative = never)
max_lifetime_msHard cap on session age (live or paused). Auto-pauses when reached — permanently: unlike every other trigger in this table, this pause can never be resumed from (any attempt refuses with 410); destroy is only a fallback if the pause itself fails. paused_ttl_ms above is what actually bounds how long the paused data sticks around
destroy_on_completionTear down after the first command (stateless-style)

max_lifetime_ms set together with paused_ttl_ms negative ("never") is rejected at create time (400): a session that max_lifetime_ms permanently pauses and can never resume from would otherwise sit paused and billed forever with no paused_ttl_ms to ever reclaim it. Set paused_ttl_ms to 0 (default) or a positive value whenever you set max_lifetime_ms.

What counts as activity (resets idle): exec, files, expose, process APIs, and an attached PTY. A background process alone does not, unless you start it with keep_alive: true.

inis sessions create --on-detach pause --paused-ttl-ms 86400000   # drop after a day paused
inis sessions create --on-detach keep_live                       # stay live after detach; idle still applies later

Limits

Defaults and hard caps on the managed cloud today:

KnobDefaultHard cap
idle_timeout_msOff (no auto-pause)1 hour
max_lifetime_msOff (no cap of your own)24 hours
Continuous-live backstopAlways on — 24 hours continuously live (6 hours on a new, unverified trial account), independent of max_lifetime_ms. Any pause/resume resets the clock24 hours (6 on trial)
paused_ttl_ms30 days— (negative disables it)
timeout_ms (one exec)30 seconds1 hour
Concurrent live sessions per account10 (1 on a new, unverified trial account)—
Cumulative disk across live + paused sessions50 GB (5 GB on trial)—

A session lives until you destroy it, it idles out, or its own opt-in max_lifetime_ms fires — there is no default cap on total age.

The continuous-live backstop never destroys — and it doesn't leave you down, either. When it fires it force-pauses (closing any attached PTY, tunnel, or in-flight operation), takes a fresh snapshot, and — normally — immediately resumes the session again: a few-second "blip," not a daily outage. That resume-from-fresh-snapshot cycle doubles as a daily durability checkpoint for a session that would otherwise never produce one. A session.active_window_warning event fires a few minutes ahead of the blip on the account event stream so you can quiesce in-guest work first — see Execution log.

The one exception: if the backstop fires while your session's host node happens to be draining for a fleet cycle, it skips the immediate resume and leaves the session parked instead — the same behavior as before this cycling existed. That's rare and self-resolving: any later request resumes the session normally, same as any other paused session.

No requests-per-second limit applies to the execution API itself — the concurrency cap is what bounds usage. Sign-in and CLI-pairing endpoints are separately rate-limited per IP/email as a brute-force guard.

Keeping a session live

To avoid idle pause while work continues without API traffic:

  • Keep a PTY attached (inis ssh)
  • Start a named process with keep_alive: true
  • Use on_pty_detach: keep_live so disconnecting does not pause immediately

Without keep_alive, a detached process can keep running until idle pause freezes the whole VM.

Billing (short)

  • Live — compute, metered by the millisecond of run time; starting and stopping are not billed
  • Paused — storage for the saved session (tier may change; you still pay while it exists)
  • Destroyed — nothing ongoing

Prefer pause over destroy when you will return: you keep the environment and avoid another template cold start.

Recipes

Agent — pause between model turns

session = client.sessions.create(template="python", idle_timeout_ms=60_000)
session.exec(["pip", "install", "httpx", "-q"])
# ... tool calls ...
session.pause()  # optional; idle timeout would do this anyway
session.exec(["python", "agent_step.py"])  # wakes automatically

Start from a template, save a baseline

SID=$(inis sessions create --template data-science)
# ... install project deps, seed data ...
inis sessions checkpoint "$SID" --name ready
# later: roll back in place, or stamp new sessions from the checkpoint

Preview server that should stay up

session.start_process("web", ["python3", "-m", "http.server", "8080"], keep_alive=True)
session.expose(8080)

If the session later pauses, preview clients disconnect; after wake they reconnect to the same URL.

If a node fails

Sessions run on dedicated hardware, and hardware occasionally dies. If a session's host is unexpectedly lost, the session moves to a terminal node_lost state — it does not silently retry, and inis.run does not auto-restore it onto another node. Every operation against it (exec, files, pty, pause, fork, checkpoint, resume) returns the session_node_lost error, with two exceptions: GET /v1/sessions/{id} keeps working and reports state: "node_lost", so you can detect it instead of guessing from a timeout, and DELETE /v1/sessions/{id} still works too — deleting a lost session always succeeds, so it never lingers, undeletable, in your session list.

Recreate the session from its template, or restore from your last checkpoint if you took one — anything since that checkpoint is gone. See Errors for the full code reference and Production best practices for a handler that branches on it.

Gotchas

  • Tier is informational — you cannot force hot; long idle or disk pressure can move a session to cold before the next wake.
  • Cold wake is slower — treat it as normal for abandoned sessions, not an error.
  • on_pty_detach is PTY-only — API-only sessions use idle timeout / explicit pause.
  • Previews drop on pause — preview connections drop while the session is paused; reconnect after wake.
  • Secrets in paused / checkpointed state — values already in guest memory can be retained with the saved session. See Sessions API.
  • Wake races — a live-only call that hits a just-paused session may return session_not_live (409); refetch and retry. See Errors.

Where to go next

  • Templates — official set, versioning, pinning
  • Best practices — persistence, resume/fork, templates, scoped credentials, egress
  • Concepts — fork, checkpoints, preview URLs
  • Sessions API — request/response reference
  • CLI — inis sessions, inis ssh
  • Networking — egress across pause / fork
  • Production best practices — which timer to reach for, why you don't need your own warm pool, reconnecting after resume

On this page