Skip to content
Runtime

How to read a sandbox's CPU and memory metrics

Call sbx.metrics({ range: "1h" }). latest is the newest reading, and points is the series. The sandbox's host takes both measurements.

On Runtime the CPU metric is the same reading the bill is made from. The host measures each running sandbox's CPU time at least every half minute, and Runtime charges $0.025 per active vCPU-hour of that measured CPU, with a floor of 50 millicores (pricing). So the chart that shows a sandbox idling also shows why it costs little: a 2 vCPU, 4 GiB sandbox that waits costs $0.03125 an hour, and $0.08 with both CPUs busy. Metrics, events and export cost nothing extra (metrics and webhooks).

Read them

TypeScriptimport { Sandbox } from "withruntime";await using sbx = await Sandbox.create();await sbx.exec("python3 -c 'sum(i * i for i in range(10**8))'", { timeoutMs: 120_000 });const m = await sbx.metrics({ range: "15m" });console.log(m.latest?.cpuPercent, m.latest?.memoryBytes);for (const p of m.points) console.log(p.at, p.cpuCores, p.cpuPeakPercent, p.memoryPeakBytes);
Pythonfrom withruntime import Sandboxwith Sandbox.create() as sbx:    sbx.exec("python3 -c 'sum(i * i for i in range(10**8))'", timeout_ms=120_000)    m = sbx.metrics(range="15m")    latest = m["latest"]    if latest:        print(latest["cpuPercent"], latest["memoryBytes"])    for point in m["points"]:        print(point["at"], point["cpuCores"], point["memoryPeakBytes"])
Terminalnpx withruntime sandboxes metrics <id> --range 6h

The same readings appear as charts on the Metrics tab of a sandbox's page in your account, under Sandboxes. The sandbox list also shows each sandbox's current CPU and memory. An agent reads them with the runtime_sandboxes_metrics MCP tool.

What each field means

Field Meaning
cpuPercent CPU in use as a percent of all the sandbox's vCPUs, 0 to 100
cpuCores The same, as a number of cores
cpuPeakPercent The busiest interval between two readings inside the bucket
memoryBytes Memory the sandbox's machine holds, as its host measures it
memoryPeakBytes The most it held inside the bucket
diskUsedBytes Bytes used on the root file system, as df / in the sandbox reports
latest The newest reading while the sandbox runs; null when it is not running

Each point also has the disk's reads and writes (diskReadBytesPerSecond, diskWriteBytesPerSecond, diskReadOpsPerSecond, diskWriteOpsPerSecond) and the network's traffic (networkReceivedBytesPerSecond, networkSentBytesPerSecond). Each is null where it was not measured (all the fields).

range sets the window. Each point sums one bucket:

range Bucket Kept for
15m 10 seconds 24 hours
1h 20 seconds 24 hours
6h 2 minutes 24 hours
24h 8 minutes 24 hours
7d, 30d 1 hour 30 days

Size a sandbox from its readings

You choose a sandbox's size with vcpu and memoryMiB. The readings show whether you chose well:

  • Memory. Memory is billed on the amount you reserve, at $0.0075 per GiB-hour. If the largest memoryPeakBytes over a week of runs is 1.2 GiB, a 2 GiB sandbox can run the same work as a 4 GiB one, at half the memory charge. The response also includes memoryLimitBytes for comparison.
  • CPU. CPU is billed on use, so extra vCPUs cost nothing while idle. A cpuPeakPercent near 100 during builds or tests means that more vcpu would finish the work sooner. The bill follows the work done.
TypeScriptimport { Sandbox } from "withruntime";const sbx = await Sandbox.connect("<sandbox id>");const week = await sbx.metrics({ range: "7d" });const peak = Math.max(0, ...week.points.map((p) => p.memoryPeakBytes));console.log(  `peak ${(peak / 2 ** 30).toFixed(2)} GiB of ${(week.memoryLimitBytes / 2 ** 30).toFixed(0)} GiB`,);

To see what you were charged, per resource, runtime usage and GET /v1/usage both return the settled figures.

Send them to your own dashboards

An OpenTelemetry export sends every sandbox's readings as OTLP gauges, about every 30 seconds, to Grafana, Honeycomb, Datadog, New Relic, or any endpoint that accepts OTLP over HTTP:

TypeScriptimport { Runtime } from "withruntime";const runtime = new Runtime();await runtime.otel.create({  endpoint: "https://api.honeycomb.io",  headers: { "x-honeycomb-team": process.env.HONEYCOMB_KEY ?? "" },  signals: ["metrics"],});

The gauges are runtime.sandbox.cpu.utilization, runtime.sandbox.cpu.usage, runtime.sandbox.memory.usage, runtime.sandbox.memory.limit, runtime.sandbox.disk.usage and runtime.sandbox.disk.limit. The disk's and the network's traffic are the sums runtime.sandbox.disk.io, runtime.sandbox.disk.operations and runtime.sandbox.network.io. Each sandbox is one resource, with its id, name, vCPUs and region. Add "traces" to signals for a span of every API call. An account can have three exports (OpenTelemetry export).

Mistakes and how Runtime handles them

  • Reading cpuPercent as per core. It is a share of all the sandbox's vCPUs. On a 2 vCPU sandbox, 50 means one core busy; cpuCores says 1.
  • Expecting readings from a paused sandbox. A paused or stopped sandbox has no new readings, and its earlier ones stay. latest is null while it is not running.
  • Looking for last month's detail. Each reading is kept 24 hours, and hourly averages and peaks 30 days. Export them to keep more.
  • Code written for E2B. Its getMetrics() works through withruntime/e2b and reads these same values, diskUsed included.

Start

Terminalprintf '%s\n' 'print(sum([125, 250, 375]))' > invoice.pynpx withruntime sandboxes run --keep -- python3 - < invoice.py

A new account gets 100 free hours of a 1 GB machine in its first 30 days, with no card. Then run runtime sandboxes metrics <id> on the kept sandbox.

Facts on this page were checked on 26 October 2026.

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