# 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: ```ts check import { 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; } ``` ```python check from withruntime import Sandbox def 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 sbx ``` The 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](/docs/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: ```ts check import { 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 browser ``` ```python check from withruntime import Sandbox sbx = 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 browser ``` A 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: true`** keeps a paid sandbox running for as long as the account has credit, and keeps its disk after a stop so `restart()` brings it back. Cap it with `maxTotalCostMicros`. - **A volume** is a disk that outlives any one sandbox: attach it at `/data` to keep work separate from the machine ([storage](/docs/storage)). ```ts check import { 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](/docs/images) 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](/docs/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: ``` CPU: 44 h × 0.3 vCPU × $0.025 = $0.33 Memory: 44 h × 4 GiB × $0.0075 = $1.32 Paused: 2 GB × $0.08 × 676 h / 720 h = $0.15 Total: $1.80 ``` A 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](/docs/pricing#paused-storage)). New accounts get 50 free sandbox hours, no card; trial sandboxes keep a pause for seven days free. ## Start ```bash no-run npx withruntime sandbox run --trial --keep -- git --version ``` The 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](/docs/javascript#sandboxes-by-name) or [Python](/docs/python#sandboxes-by-name) SDK as above. Related: [pause and resume a sandbox](/how-to/pause-and-resume-a-sandbox), [coding agent sandbox](/use-cases/coding-agent-sandbox), [preview apps an agent builds](/use-cases/preview-agent-built-apps), [run Docker in a sandbox](/how-to/run-docker-in-a-sandbox). Facts on this page were checked on 25 September 2026.