This page focuses on the details that aren’t obvious from the API surface alone — what actually survives a restart, how long a sandbox lives, and where the sharp edges are. If you only read one section, read Filesystem and persistence.
Quickstart
Plans and pricing
Sandboxes come in multiple plan sizes, from a quick script to a heavier data-processing run. If you don’t passplan, you get medium — not the cheapest tier. Disk scales with plan.
For current plan specs (vCPU, RAM, disk) and hourly pricing, don’t hardcode numbers — check the live catalog:
- Dashboard: deepinfra.com/dash/sandboxes#catalog
- API:
GET /v1/sandboxes/catalog(see HTTP API), orSandbox.catalog()in the Python SDK
creating, starting, running, or stopping — a stopped sandbox costs nothing. Because the meter starts while the microVM is still booting and keeps running for the few seconds it takes to save your disk on stop(), per-call cost is “wall clock the sandbox occupied capacity,” not strictly “wall clock you could run commands.”
Lifecycle and timeouts
Operations are tied to state:
exec() and fs.read()/fs.write() require running; stop() requires running or starting; start() requires stopped. Calling one from the wrong state returns a 409/ConflictError.
A sandbox is subject to three independent clocks:
- Idle timeout — configurable per sandbox with
timeoutat creation (an hour, by default, if you don’t pass one, and there’s currently no way to disable it). Idle time is measured from when your last call finished, not when it started, so a single command that runs longer than the idle timeout can have its sandbox stopped out from under it mid-execution. If a job might take a while, settimeoutgenerously (up to the 30-minute per-command cap) rather than relying on the default. - 24-hour running limit — a sandbox auto-stops after 24 continuous hours of
running. This resets every time youstart()it, so stopping and restarting doesn’t carry over — only the current run counts toward the 24h cap. You canstop()/start()the same sandbox indefinitely; there’s no need toterminate()and recreate it just to reset the clock. - Retention after stop — a
stoppedsandbox has up to 7 days to bestart()-ed again before it’s permanently deleted,/workspaceincluded.
exec() command has its own timeout: 60 seconds by default, up to a hard cap of 30 minutes.
Filesystem and persistence
The persistence model is narrower than “it’s a VM, everything sticks around” — this is the part worth reading closely. Only/workspace survives a stop() / start() cycle. Everything else — packages installed outside it, environment changes, background processes, anything written to /tmp, /root, or elsewhere — is gone the moment you start() again. That’s because start() always boots a fresh container from the base image; it never resumes a suspended VM. Only /workspace’s contents come back. The rest of the container’s own disk is small (a couple GB) regardless of plan, so treat /workspace as the one place anything you need to keep should live — don’t count on pip install-ed packages surviving a stop.
fs.read() and fs.write() enforce this directly: paths outside /workspace are rejected with 400 (BadRequestError), not silently redirected. Reading a path that doesn’t exist returns 404; reading something that isn’t a regular file (a directory, for instance) also returns 400. Both directions are capped at 100 MiB per call (413 / ContentTooLargeError) — the same limit applies whether you’re writing or reading.
exec() isn’t restricted the same way — a shell command can write anywhere on disk — but only what lands under /workspace will be there the next time you start().
Persistence is also conditional on a clean stop. If a sandbox crashes or is marked unhealthy — a node issue, an out-of-memory kill, anything that isn’t you calling stop() — it goes to failed, and its /workspace is not preserved; the sandbox is torn down within a few minutes and any unsaved work in it is gone. Only an explicit stop() guarantees your data comes back.
Isolation and networking
Every sandbox boots as its own microVM — via Kata Containers running on QEMU/KVM — with its own kernel and its own virtualized hardware boundary, not a namespaced slice of a host shared with other tenants. Networking is locked down to match:- A sandbox can reach the public internet (so
pip installworks), but accepts no inbound connections at all. - It can’t reach other sandboxes or DeepInfra’s internal infrastructure.
- Egress and ingress are each capped at 200 Mbit/s.
- Outbound SMTP (ports 25, 465, 587) is blocked.
Limits and quotas
- Active sandboxes — up to 5 non-stopped sandboxes per account at a time.
creating,starting,running, andstoppingall count against this;stoppeddoesn’t. Going over it returns a429(RateLimitError, aliased asTooManySandboxesErrorin the SDK) instead of a silent failure. - Fleet capacity — sandboxes run on a shared fleet, so a capacity crunch across all customers can occasionally return a
503(CapacityError) on creation even when you’re well under your own limit. Retry with backoff. - File transfers — both
fs.write()andfs.read()are capped at 100 MiB per call (see above). - Disk — scales with plan (see the catalog for exact numbers); the container’s own disk outside
/workspaceis only a couple GB regardless of plan.
Tags
Attach your own string key/value tags at creation time for bookkeeping:GET, list) and can be used to filter client-side:
Errors
The Python SDK adds a few client-side exceptions for conditions that aren’t a single HTTP response:
SandboxTimeoutError (waiting for a state transition took too long), SandboxFailedError (the sandbox went to failed while you were waiting on it), SandboxExecError (the exec stream ended without a return code), and CommandFailedError (raised by .check() on a non-zero exit).
Python SDK
DEEPINFRA_API_KEY (the same key you use for inference, from deepinfra.com/dash/api_keys) and you’re executing code in an isolated microVM in a few lines — see the Quickstart above.
A few things worth knowing beyond the basic example:
timeoutaccepts plain seconds (600) or a duration string ("90s","10m","2h","1h30m").Sandbox.create()blocks until the sandbox isrunningby default. Passwait=Falseto get it back immediately in whatever state it’s in, orwait_timeout=to change how long to wait.Sandbox.from_id("sb-...")reattaches to a sandbox by ID from anywhere in your code — you’re not stuck driving it from the process that created it.- Every network method has an
a-prefixed async twin (acreate,aexec,aterminate, and so on), so orchestrating many sandboxes at once is a normalasyncioprogram:
- A sandbox terminates automatically when used as a context manager:
- For large scripts, write the file and run it rather than passing code inline:
exec_stream() for live command output, snapshot() / Sandbox.from_snapshot() for point-in-time snapshots you control, expose_port(), and fs.upload_dir().
HTTP API
Everything above is also available directly over HTTP. Authenticate with your API key. Create a sandbox:application/x-ndjson, one JSON object per line, ending in exactly one terminal line ({"returncode": N} on completion, or {"error": "..."} if the command timed out or otherwise couldn’t finish):
This streamed response is always HTTP
200 once it starts — a mid-command failure (timeout, oversized output, and so on) shows up as {"error": ...} in the terminal line, not as an HTTP error status. Check the last line, not just the status code./workspace and capped at 100 MiB per call:
FAQ
What happens to my data when I stop a sandbox? Nothing under/workspace is lost — it’s preserved and restored when you start() again. Everything else in the container (installed packages, environment changes, /tmp, /root) is reset, because start() boots a fresh container rather than resuming the old one.
How long does a sandbox actually live?
Three independent clocks apply: it idles out after its configured timeout (1 hour by default) with no activity, it auto-stops after 24 continuous hours of running (this resets on every start(), so repeated stop/start cycles don’t add up), and once stopped it’s permanently deleted after 7 days if you don’t start it again.
What happens if my sandbox crashes?
It moves to failed and is deleted within about 5 minutes — /workspace is not preserved in this case. Only a clean stop() guarantees your data survives.
Can a sandbox reach other sandboxes, or my own infrastructure?
No. It can reach the public internet, but not other sandboxes and not DeepInfra’s internal infrastructure.
Why did my fs.read()/fs.write() call fail?
Most likely the path was outside /workspace, which comes back as 400. A 404 means the file doesn’t exist; 413 means the file is over the 100 MiB transfer cap.
What happens if my account is suspended?
Sandbox creation, start(), and any exec/file-transfer calls are blocked (402) while your account is suspended — for example, when your balance runs out. stop() and terminate() still work, so you can shut down a sandbox (and its billing) even while suspended. Consider Automatic Top-Up if you’re running unattended jobs.
Where do I see what my sandboxes are costing me?
On the Usage page.