Runtime

How to run Bun code in a cloud sandbox

Bun 1.4.0 is preinstalled in every Runtime sandbox: write your file into the microVM and run bun on it, TypeScript and tests included.

On Runtime, Bun needs no install step, and the SDK runs on Bun too. Every sandbox is a Firecracker microVM with its own kernel and Bun 1.4.0 next to Node.js 24.21.0. A new sandbox answered its first command 351 ms after the request at the median on 24 September 2026 (speed). A 2 vCPU, 4 GiB sandbox costs $0.08 an hour with both CPUs busy and $0.03125 an hour while it waits, because Runtime bills the CPU your code uses (pricing).

Run a Bun script

TypeScriptimport { Sandbox } from "withruntime";const script = `const words = "the quick brown fox jumps over the lazy dog".split(" ");const longest: string = words.reduce((a, b) => (b.length > a.length ? b : a));console.log(longest, Bun.version);`;await using sbx = await Sandbox.create({  network: { internet: false },  timeoutSeconds: 300,  onLeaseEnd: "stop",});await sbx.files.write("/workspace/job.ts", script);const run = await sbx.exec(["bun", "job.ts"], { timeoutMs: 20_000 });console.log(run.exitCode, run.stdout);
Pythonfrom withruntime import Sandboxscript = """const words = "the quick brown fox jumps over the lazy dog".split(" ");const longest: string = words.reduce((a, b) => (b.length > a.length ? b : a));console.log(longest, Bun.version);"""with Sandbox.create(network={"internet": False}, timeout_seconds=300, on_lease_end="stop") as sbx:    sbx.files.write("/workspace/job.ts", script)    run = sbx.exec(["bun", "job.ts"], timeout_ms=20_000)    print(run.exit_code, run.stdout)

Bun "supports TypeScript and JSX with no configuration" and transpiles each file before it runs (Bun). It does not type-check; see TypeScript in a sandbox for tsc.

What is in the image

Tool Version or detail
Bun 1.4.0 (bun)
Node.js 24.21.0 (node, npm, npx)
unzip In the image; Bun's own installer needs it on Linux
Build tools gcc, g++, make
OS Ubuntu 24.04.5 LTS (noble), amd64, 6.1 kernel

Commands run as the user runtime with /workspace as home and working directory, and sudo works without a password (the sandbox environment).

Run a test suite with bun test

bun test is Bun's built-in, Jest-compatible runner. It finds files named *.test.ts, *_test.ts, *.spec.ts and *_spec.ts (and the JavaScript forms), and each test times out after 5,000 ms unless you pass --timeout (Bun test).

TypeScriptimport { Sandbox } from "withruntime";await using sbx = await Sandbox.create({ timeoutSeconds: 1200, onLeaseEnd: "stop" });await sbx.files.upload("./my-app", "/workspace/app");await sbx.exec("cd app && bun install", { check: true, timeoutMs: 300_000 });await sbx.network.set({ internet: false }); // tests run with no networkconst run = await sbx.exec(["bun", "test", "--timeout", "20000"], {  cwd: "/workspace/app",  timeoutMs: 600_000,  onStdout: (text) => process.stdout.write(text),});process.exitCode = run.exitCode ?? 1;
Pythonimport sysfrom withruntime import Sandboxwith Sandbox.create(timeout_seconds=1200, on_lease_end="stop") as sbx:    sbx.files.upload("./my-app", "/workspace/app")    sbx.exec("cd app && bun install", check=True, timeout_ms=300_000)    sbx.network.set(internet=False)  # tests run with no network    run = sbx.exec(["bun", "test", "--timeout", "20000"], cwd="/workspace/app",                   timeout_ms=600_000, on_stdout=sys.stdout.write)    sys.exit(1 if run.exit_code is None else run.exit_code)

A timeoutMs over 60 seconds streams the output, and the result keeps everything the tests printed. Cutting the network after the install keeps a test that calls out from reaching anything.

Serve a Bun app

Start a server with spawn, not exec: everything an exec starts ends with its command. Then share the port as a private HTTPS preview.

TypeScriptimport { Sandbox } from "withruntime";await using sbx = await Sandbox.create({ timeoutSeconds: 1800 });await sbx.files.write(  "/workspace/server.ts",  'Bun.serve({ port: 3000, fetch: () => new Response("hello from bun") });',);const server = await sbx.spawn(["bun", "server.ts"]);await sbx.exec("sleep 1 && curl -s localhost:3000", { check: true });console.log(server.id);

A newer Bun, or the same Bun in every sandbox

Bun's installer puts Bun in ~/.bun/bin, takes a version as bash -s "bun-v<version>", and needs unzip (Bun installation). To pin one release for every sandbox, run it in a custom image recipe with BUN_INSTALL pointing at /usr/local, so bun lands on the sandbox user's PATH:

TypeScriptimport { Runtime } from "withruntime";const runtime = new Runtime();await runtime.images.build({  name: "bun-app",  recipe: {    commands: ["curl -fsSL https://bun.com/install | BUN_INSTALL=/usr/local bash"],    npm: ["zod"],  },});await using sbx = await runtime.sandboxes.create({ image: "bun-app" });console.log((await sbx.exec(["bun", "--version"])).stdout);
Pythonfrom withruntime import Runtimeruntime = Runtime()runtime.images.build(name="bun-app", recipe={    "commands": ["curl -fsSL https://bun.com/install | BUN_INSTALL=/usr/local bash"],    "npm": ["zod"],})with runtime.sandboxes.create(image="bun-app") as sbx:    print(sbx.exec(["bun", "--version"]).stdout)

Recipe commands run as root in /workspace. Building an image is free; a stored image is charged on its size.

Drive sandboxes from Bun

The withruntime package supports Bun as well as Node 22 or later, and await using works on Bun, so a Bun service can create, run and stop sandboxes with the samples above unchanged (JavaScript SDK).

Terminalbun add withruntime

New accounts get 50 free sandbox hours, no card:

Terminalnpx withruntime sandbox run --trial -- bun --version

Sources

Facts on this page were checked on 25 September 2026.