Skip to content
Runtime

How to run a coding playground for your users

Run each visitor's code in its own microVM sandbox. Keep the internet off. Set a time limit per run, and keep a warm interpreter between runs.

On Runtime, 20,000 playground sessions a month cost about $55.56, a quarter of a cent each, on 1 vCPU, 2 GiB sandboxes. The figure uses the rates in effect on 26 October 2026. Runtime bills the CPU the code uses. So a session where the visitor spends most of the time reading and typing costs little. One interpreter covers Python, JavaScript, TypeScript, R, Java, Bash and Go. gcc and g++ cover C and C++.

The short answer

Use one sandbox per browser session, found again by name. Cut the network, and set a limit on every run:

TypeScriptimport { Sandbox } from "withruntime";type Language = "python" | "javascript" | "typescript" | "go" | "java" | "r" | "bash";export async function runSnippet(sessionId: string, language: Language, code: string) {  const sbx = await Sandbox.getOrCreate(`play-${sessionId}`, {    vcpu: 1,    memoryMiB: 2048,    idlePauseSeconds: 300, // pause five minutes after the last run    network: { internet: false },    maxTotalCostMicros: 100_000, // stop it once it has cost 10 cents    labels: { kind: "playground" },  });  const cell = await sbx.interpreter.run(code, { language, timeoutMs: 10_000 });  return {    status: cell.status, // "ok", "error" or "timeout"    stdout: cell.stdout,    stderr: cell.stderr,    error: cell.error?.traceback ?? null,  };}console.log(await runSnippet("s-1", "python", "total = sum(range(10))\nprint(total)"));console.log(await runSnippet("s-1", "python", "print(total * 2)")); // state carries over
Pythonfrom withruntime import Sandboxdef run_snippet(session_id: str, language: str, code: str) -> dict:    sbx = Sandbox.get_or_create(        f"play-{session_id}",        vcpu=1,        memory_mib=2048,        idle_pause_seconds=300,  # pause five minutes after the last run        network={"internet": False},        max_total_cost_micros=100_000,  # stop it once it has cost 10 cents        labels={"kind": "playground"},    )    cell = sbx.interpreter.run(code, language=language, timeout_ms=10_000)    return {"status": cell["status"], "stdout": cell["stdout"], "stderr": cell["stderr"],            "error": (cell["error"] or {}).get("traceback")}print(run_snippet("s-1", "python", "total = sum(range(10))\nprint(total)"))print(run_snippet("s-1", "python", "print(total * 2)"))  # state carries over

Variables persist between runs, the way a notebook works. So a visitor's second run can use what the first run defined. For a clean slate, stop the sandbox. The next run then creates a new one.

Languages, and how each one runs

Language How the playground runs it First use in a sandbox
Python 3.12 Interpreter, state kept between runs Ready; NumPy, pandas, matplotlib included
JavaScript, TypeScript Interpreter, on Node.js 24 Ready
Bash Interpreter Ready
Go Interpreter; keeps functions, types and imports Installed once, about 35 seconds
Java Interpreter Installed once, about 35 seconds
R Interpreter; plots return as PNG Installed once, about 90 seconds
C, C++ gcc or g++ through exec, then the binary Ready
Rust rustup baked into a custom image Build the image once

The install times were measured on 23 September 2026. To skip them, build an image with those languages. Then start playground sandboxes from that image (custom images).

C and C++ go through a file and a fixed command. The visitor's code is data, and it is never part of the shell line:

TypeScriptimport { Sandbox } from "withruntime";await using sbx = await Sandbox.create({ network: { internet: false } });await sbx.files.write("/workspace/main.c", '#include <stdio.h>\nint main(){puts("hi");}\n');const build = await sbx.exec(["gcc", "-O2", "-o", "main", "main.c"], { timeoutMs: 20_000 });const run = build.exitCode === 0 ? await sbx.exec(["./main"], { timeoutMs: 5_000 }) : build;console.log(run.exitCode, run.stdout, run.stderr);

Stop a playground from being abused

A public playground runs code from strangers. Each guard below is enforced outside the code's reach:

Abuse Guard
Escaping to your servers A Firecracker microVM with its own kernel per session
Sending traffic out internet: false, enforced on the host; root in the sandbox cannot undo it
An infinite loop timeoutMs per run; the run returns a timeout, with the output so far
Flooding the page with output Each result holds at most 64 KiB of stdout and 64 KiB of stderr
Filling memory or disk The sandbox's own memoryMiB and diskMiB; other sessions are unaffected
Unexpected charges maxTotalCostMicros per sandbox, a daily spending limit on the key, pause when idle
Too many sessions at the same time Creates past the account limit wait for room instead of failing

Runtime's acceptable use policy applies to what your visitors run too. Keep the internet off unless a lesson needs it. When one does, allow only that host with network.allow.

Stream output as it prints

For programs that print over time, stream to the browser instead of waiting:

TypeScriptimport { Sandbox } from "withruntime";await using sbx = await Sandbox.create({ network: { internet: false } });await sbx.interpreter.run(  "import time\nfor i in range(3):\n    print(i, flush=True)\n    time.sleep(1)",  {    timeoutMs: 10_000,    onStdout: (text) => process.stdout.write(text), // send each chunk over your WebSocket  },);

What a coding playground needs

Need How Runtime covers it
Many languages Seven interpreter languages, plus gcc and g++
A session that remembers Named sandboxes with getOrCreate; variables persist between runs
Fast first run A new microVM per run, from a machine started ahead of time for the common shapes
Cheap idle sessions Measured CPU while running; idlePauseSeconds pauses quiet ones
Isolation between visitors One microVM per session
Nothing leaves Internet off per sandbox

What it costs

Assume 20,000 sessions a month. Each keeps a 1 vCPU, 2 GiB sandbox running for 10 minutes, idle pause included. The visitor's runs use 40 CPU-seconds. Each sandbox is stopped when the session ends:

CPU
20,000 × 40 s / 3,600 × $0.025
$5.56
Memory
20,000 × 10 min / 60 × 2 GiB × $0.0075
$50.00
Total
$55.56

A session's CPU never bills below the floor of a twentieth of a vCPU. Over 10 minutes, that floor is 30 CPU-seconds. So 40 CPU-seconds is above it. Runtime charges $0.025 per vCPU-hour of measured CPU and $0.0075 per GiB-hour of memory (pricing).

Start

Terminalnpx withruntime sandboxes run -- node -e 'console.log(6 * 7)'

Approve the browser link once. runtime sandboxes run-code <id> - --lang go < main.go runs a file in any interpreter language from a terminal (CLI).

Related: online IDE on sandboxes, coding interview platform, grade student code, run untrusted LLM code, Go in a sandbox.

Facts on this page were checked on 26 October 2026.

Related.

100 free hoursin your first 30 days.

of a 1 GB machine

  • No credit card
  • Four sandboxes at once, 2 vCPU and 4 GiB each
  • Then prepaid credit from $10, no plan fee
Start free, no card
Start free, no card