Skip to content

Languages

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 work without extra setup.

Updated · Facts checked · By Runtime Cloud

4 min read

Read as Markdown

On Runtime, Bun needs no install step, and the SDK runs on Bun too. Every sandbox is a Firecracker microVM with its own kernel. Bun 1.4.0 is installed next to Node.js 24.21.0. A 2 vCPU, 4 GiB sandbox costs $0.08 an hour with both CPUs busy, and $0.03125 an hour while it waits. 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". It transpiles each file before it runs (Bun). Bun does not type-check. For tsc, see TypeScript in a sandbox.

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.18 kernel

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

Run a test suite with bun test

bun test is Bun's built-in runner, and it is compatible with Jest. It finds files named *.test.ts, *_test.ts, *.spec.ts and *_spec.ts, and the JavaScript forms of those names. 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)

With timeoutMs over 60 seconds, output streams, 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 that exec starts ends when its command ends. 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. It takes a version as bash -s "bun-v<version>", and it needs unzip (Bun installation). To pin one release for every sandbox, run the installer in a custom image recipe. Set BUN_INSTALL to /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 by its size.

Drive sandboxes from Bun

The withruntime package supports Bun as well as Node 22.12 or later. await using works on Bun. A Bun service can therefore create, run and delete sandboxes with the samples above, unchanged (JavaScript SDK).

Terminalbun add withruntime

A new account gets 100 free hours of a 1 GB machine in its first 30 days, with no card required:

Terminalnpx withruntime sandboxes run -- bun --version

Sources

Facts on this page were checked on 26 October 2026.

Cut your cloud billby 75%.

No card to start. Billed by the second after.

Start free, no card