How to give every user their own cloud dev environment
Give each user a named sandbox that pauses when idle and wakes on the next request, with their files, memory and processes kept in between.
On Runtime a developer's environment costs about $1.80 a month when it runs two hours a working day and sleeps the rest, because Runtime bills the CPU it uses and a paused sandbox pays only for storage. The working is below. A paused sandbox wakes in about half a second, with its processes still running, and is kept for 1 to 365 days.
The short answer
Name each environment after its user. getOrCreate returns that user's
sandbox, woken if it paused, or creates it the first time:
TypeScriptimport { Sandbox } from "withruntime";export async function devEnvironment(userId: string) { const sbx = await Sandbox.getOrCreate(`dev-${userId}`, { labels: { kind: "dev", user: userId }, diskMiB: 16_384, idlePauseSeconds: 900, // pause after 15 minutes with no request }); if (!sbx.info.reused) { await sbx.exec("git clone https://github.com/your-org/your-repo.git app", { check: true, timeoutMs: 300_000, }); } return sbx;}Pythonfrom withruntime import Sandboxdef dev_environment(user_id: str): sbx = Sandbox.get_or_create( f"dev-{user_id}", labels={"kind": "dev", "user": user_id}, disk_mib=16_384, idle_pause_seconds=900, # pause after 15 minutes with no request ) if not sbx.info.get("reused"): sbx.exec("git clone https://github.com/your-org/your-repo.git app", check=True, timeout_ms=300_000) return sbxThe next day, the same call answers the same sandbox with the same files, and any server or REPL left running is still running. A name is unique in the account while its sandbox can still run, so two requests for one user never make two environments.
How the user gets in
| Way in | How |
|---|---|
| A shell | runtime sandbox ssh dev-alice, or sbx.terminal() in your own web terminal |
| VS Code or JetBrains | runtime sandbox ssh config --install, then connect to host dev-alice.runtime |
| A local port | runtime sandbox port-forward dev-alice 5432 for a database, debugger or dev server |
| A browser tab | A private HTTPS preview of the dev server's port |
| An agent | The same sandbox through the SDK, the CLI or Runtime's MCP server |
Everything goes through Runtime's API with the user's key; the sandbox opens no port to the internet (SSH and editors). A request of any of these kinds wakes a paused sandbox, and a browser visiting a shared port sees a short "Waking up" page that reloads itself.
Show the running app
Start the dev server with spawn, which keeps it running after your call
returns, and share its port:
TypeScriptimport { Sandbox } from "withruntime";const sbx = await Sandbox.getOrCreate("dev-alice", { idlePauseSeconds: 900 });await sbx.spawn("cd app && npm run dev -- --port 3000");const preview = await sbx.previews.create(3000);console.log(preview.urlWithToken); // a one-time link for the user's browserPythonfrom withruntime import Sandboxsbx = Sandbox.get_or_create("dev-alice", idle_pause_seconds=900)sbx.spawn("cd app && npm run dev -- --port 3000")preview = sbx.previews.create(3000)print(preview["urlWithToken"]) # a one-time link for the user's browserA preview is private by default: a request needs its token, and
previews.rotate(port) refuses every token issued so far.
Always on, or asleep when idle
Pick per environment:
idlePauseSeconds(60 to 86,400) pauses after that long with no exec, file, process, terminal, desktop or preview request. It pays running time only while in use, and paused storage in between.persistent: truekeeps a paid sandbox running for as long as the account has credit, and keeps its disk after a stop sorestart()brings it back. Cap it withmaxTotalCostMicros.- A volume is a disk that outlives any one sandbox: attach it at
/datato keep work separate from the machine (storage).
TypeScriptimport { Sandbox } from "withruntime";const lead = await Sandbox.getOrCreate("dev-lead", { funding: "paid", persistent: true, maxTotalCostMicros: 20_000_000, // at most $20 over its life});await lead.update({ idlePauseSeconds: 0 });What a per-user environment needs
| Need | How Runtime covers it |
|---|---|
| One environment per user | Names unique per account; getOrCreate finds or makes it |
| Nothing lost overnight | Pause keeps files, memory and running processes, 1 to 365 days |
| Fast return | Wake on request, usually about half a second |
| Low idle cost | Paused storage at $0.08 per GB per 30-day month; no compute while paused |
| A full Linux machine | Ubuntu 24.04, sudo, Python, Node.js, Bun, gcc; sudo enable-docker for Compose |
| The team's toolchain | A custom image from the repository's own Dockerfile |
| Users kept apart | A Firecracker microVM with its own kernel for each user |
| Team access | Owner, admin, developer and billing roles, with an audit log (teams) |
What it costs
Take one developer's 2 vCPU, 4 GiB environment running 2 hours a day on 22 working days, 44 hours a month, using on average 0.3 of a vCPU while it runs, and paused the other 676 hours with 2 GB of its own disk and memory stored:
TextCPU: 44 h × 0.3 vCPU × $0.025 = $0.33Memory: 44 h × 4 GiB × $0.0075 = $1.32Paused: 2 GB × $0.08 × 676 h / 720 h = $0.15Total: $1.80A team of 50 costs about $90 a month on those assumptions. The paused size is the disk and memory blocks the sandbox alone owns, measured when it pauses (pricing). New accounts get 50 free sandbox hours, no card; trial sandboxes keep a pause for seven days free.
Start
Terminalnpx withruntime sandbox run --trial --keep -- git --versionThe first run prints a link to approve in your browser; --keep keeps the
sandbox and prints how to run more in it. Then use the
JavaScript or
Python SDK as above.
Related: pause and resume a sandbox, coding agent sandbox, preview apps an agent builds, run Docker in a sandbox.
Facts on this page were checked on 25 September 2026.