# How to run scientific computing jobs in cloud sandboxes Build an image with your numerical stack, give each simulation or parameter its own sandbox, and read the results back as files. **On Runtime a 40-run parameter sweep of 2 hours each on 4 vCPU, 8 GiB sandboxes costs $12.80 with every core busy**, at the rates in force on 25 September 2026: $0.025 per vCPU-hour of measured CPU and $0.0075 per GiB-hour of memory, with no plan fee and no minimum. Each run gets a full Ubuntu 24.04 machine with `sudo`, gcc and Python 3.12, a new sandbox answered its first Python command 351 ms after the request at the median on 24 September 2026, and a paid account runs up to 200 vCPUs at once to start. ## The short answer: a parameter sweep Put the input data on a volume, attach it read-only to every run, and start one sandbox per parameter value in parallel: ```ts check import { Runtime } from "withruntime"; const runtime = new Runtime(); const values = [0.1, 0.2, 0.4, 0.8]; const results = await Promise.all( values.map(async (k) => { await using sbx = await runtime.sandboxes.create({ image: "sci", // built once, see below vcpu: 4, memoryMiB: 8192, labels: { sweep: "diffusion-7", k: String(k) }, volumes: [{ volumeId: process.env.INPUT_VOLUME!, path: "/data", mode: "snapshot" }], }); const release = sbx.keepAlive(); // runs can outlast the one-hour lease try { await sbx.exec( ["python3", "/data/simulate.py", "--k", String(k), "--out", "/workspace/out.npz"], { check: true, timeoutMs: 4 * 3_600_000, // one exec may run up to 24 hours }, ); return { k, npz: await sbx.files.read("/workspace/out.npz") }; } finally { release(); } }), ); console.log(results.map((r) => [r.k, r.npz.length])); ``` ```python check import asyncio import os from withruntime import AsyncRuntime async def one_run(runtime: AsyncRuntime, k: float) -> tuple[float, bytes]: async with await runtime.sandboxes.create( image="sci", vcpu=4, memory_mib=8192, labels={"sweep": "diffusion-7", "k": str(k)}, volumes=[{"volume_id": os.environ["INPUT_VOLUME"], "path": "/data", "mode": "snapshot"}], ) as sbx: release = sbx.keep_alive() # runs can outlast the one-hour lease try: await sbx.exec(["python3", "/data/simulate.py", "--k", str(k), "--out", "/workspace/out.npz"], check=True, timeout_ms=4 * 3_600_000) return k, await sbx.files.read("/workspace/out.npz") finally: release() async def main(): async with AsyncRuntime() as runtime: results = await asyncio.gather(*(one_run(runtime, k) for k in [0.1, 0.2, 0.4, 0.8])) print([(k, len(data)) for k, data in results]) asyncio.run(main()) ``` A volume in `snapshot` mode is a read-only copy that any number of sandboxes can attach at once, so forty runs read the same inputs without forty uploads. Each sandbox stops when its block ends, and billing stops with it. ## Build the numerical stack once NumPy 1.26.4, pandas and matplotlib are in the default image, with gcc, g++ and make. Everything else goes into a custom image, built from a recipe or from your lab's existing Dockerfile: ```ts check import { Runtime } from "withruntime"; const runtime = new Runtime(); await runtime.images.build({ name: "sci", recipe: { pip: ["scipy", "h5py", "numba", "xarray"] }, }); ``` ```python check from withruntime import Runtime runtime = Runtime() with open("Dockerfile") as handle: runtime.images.build(name="sci", dockerfile=handle.read(), context_dir=".") ``` Building is free and runs in its own microVM; a stored image costs $0.08 per GB per 30-day month. Each build of a name is its next version, so a paper can pin `sci@3` and rerun on exactly that environment later ([custom images](/docs/images)). ## Choose the machine for the job | Setting | What it does | When to use it | | ------------------- | ---------------------------------------------------------------------- | ------------------------------------------ | | `vcpu`, `memoryMiB` | The size you ask for, checked against account limits and host capacity | Match the solver's threads and working set | | `cpu: "shared"` | The default: bursts up to `vcpu` cores, billed on measured CPU | Most jobs, and anything that waits on I/O | | `cpu: "reserved"` | Guarantees every vCPU, and raises the charge while the CPUs are idle | Timing-sensitive benchmarks | | `diskMiB` | Disk for outputs and scratch; the only limit on file size | Large intermediate arrays | | `volumes` | Up to four per sandbox, read-write to one or read-only to many | Shared inputs; results that must be kept | | `mounts.add` | Your own S3, R2 or Google Cloud Storage bucket as a directory | Datasets already in object storage | The interpreter also runs R and Go. Java, Go and Rust install with `sudo apt-get install` or the language's own installer, or go in the image. A sandbox's disk bursts to about 250 MB/s for up to 30 seconds, then runs at about 40 MB/s, so keep heavy input on a mounted bucket or a volume rather than copying it in on every run. ## Long runs, checkpoints and reruns - **Past an hour:** a lease is at most an hour ahead. `keepAlive()` renews it while your process holds the sandbox; on a paid account `persistent: true` lets the server renew it instead, capped by `maxTotalCostMicros`. - **Survive your own laptop closing:** start the solver with `spawn` rather than `exec`. It runs in the sandbox, and `processes.get(id)` finds it again. - **Checkpoints:** write them to a read-write volume and run `sync`. Volumes are charged on their full size, 153 microdollars per GiB-hour. - **Branch a run:** `fork({ count })` copies a running sandbox, memory and processes included, so a simulation warmed up once can continue with several settings from the same state. Forks need a sandbox without volumes; give that one its inputs on its own disk. ## What a scientific workload needs | Need | How Runtime covers it | | ---------------------------- | -------------------------------------------------------------- | | A reproducible environment | Versioned images from a recipe or a Dockerfile | | Many runs at once | 100 sandboxes and 200 vCPUs at once on a paid account to start | | Shared input data | Read-only volume copies, or a mounted bucket | | Compiled code | gcc, g++, make and `sudo apt-get` in every sandbox | | Hours-long jobs | `exec` up to 24 hours; `spawn`; `keepAlive` or `persistent` | | Paying only for compute used | Measured CPU; nothing once an ordinary sandbox stops | ## What it costs Take a sweep of 40 runs, each on 4 vCPU and 8 GiB for 2 hours with all four cores busy the whole time: ``` CPU: 40 × 2 h × 4 vCPU × $0.025 = $8.00 Memory: 40 × 2 h × 8 GiB × $0.0075 = $4.80 Total: $12.80 ``` A run that spends half its time on I/O uses half the CPU and pays $4.00 less for the sweep's CPU line. A 20 GiB input volume held for the month adds 20 × 153 microdollars × 720 hours, about $2.20 ([pricing](/docs/pricing#snapshots-images-and-volumes)). ## Start ```bash no-run npx withruntime sandbox run --trial -- python3 -c 'import numpy; print(numpy.__version__)' ``` Approve the browser link the command prints. The trial runs up to eight sandboxes of 2 vCPU and 4 GiB at once; larger sizes need paid credit. Related: [CPU machine learning training](/use-cases/cpu-ml-training), [long-running agents](/use-cases/long-running-agents), [data analysis agent](/use-cases/data-analysis-agent), [sandbox forks](/glossary/sandbox-fork). Facts on this page were checked on 25 September 2026.