How to attach a persistent volume to a sandbox
Create a volume with runtime.volumes.create({ sizeMiB }), then pass volumes: [{ volumeId, path }] when you create the sandbox.
On Runtime a volume is a disk that outlives every sandbox that uses it, and it is backed up off its server every day. It costs 153 microdollars per GiB-hour, about $0.11 per GiB per 30-day month, so a 10 GiB cache costs about $1.10 a month; the free trial stores its first 10 GiB of volumes free for as long as you keep them (rates in force since 23 September 2026, pricing).
Create, attach, write
TypeScriptimport { Runtime } from "withruntime";const runtime = new Runtime();const volume = await runtime.volumes.create({ sizeMiB: 10_240, name: "cache" });await using sbx = await runtime.sandboxes.create({ volumes: [{ volumeId: volume.id, path: "/data" }],});await sbx.exec("sudo chown runtime /data && echo kept > /data/note.txt && sync");Pythonfrom withruntime import Runtimeruntime = Runtime()volume = runtime.volumes.create(size_mib=10_240, name="cache")with runtime.sandboxes.create(volumes=[{"volume_id": volume["id"], "path": "/data"}]) as sbx: sbx.exec("sudo chown runtime /data && echo kept > /data/note.txt && sync")Terminalvol=$(runtime volume create --size-mib 10240 --name cache)id=$(runtime sandbox create --volume "${vol}:/data")runtime sandbox exec "${id}" -- sh -c 'sudo chown runtime /data && echo kept > /data/note.txt'runtime sandbox stop "${id}"The first command gives /data to the sandbox user, runtime, so later
commands write to it without sudo. The next sandbox that attaches this
volume finds /data/note.txt where this one left it.
Read-write to one, read-only to many
| Mode | Who can attach it | Use it for |
|---|---|---|
rw (the default) |
One sandbox at a time | A workspace, a package cache, a database's files |
snapshot |
Any number, each a read-only copy | A dataset or model weights that many workers read |
TypeScriptimport { Runtime } from "withruntime";const runtime = new Runtime();const weights = await runtime.volumes.create({ sizeMiB: 20_480, name: "weights" });const workers = await Promise.all( [1, 2, 3].map(() => runtime.sandboxes.create({ volumes: [{ volumeId: weights.id, path: "/models", mode: "snapshot" }], }), ),);await Promise.all(workers.map((w) => w.stop()));A sandbox takes up to four volumes.
Facts to plan around
| Fact | Detail |
|---|---|
| Price | 153 microdollars per GiB-hour, on the full size, written or not |
| Charged from | The moment it is created, until it is deleted |
| Where it lives | One server; a sandbox that uses it is placed on that server |
| Daily backup | Off the server, starting an hour after creation, kept 7 days unless you set 1 to 365 |
| Backup price | $0.012 per decimal GB per 30-day month, on the bytes stored |
| Backups held | Up to 200 per organization at a time |
| Snapshots | A sandbox with volumes cannot be snapshotted |
Back it up and restore it
A backup can be made on request too, and a restore is a new volume in the same region, on whichever server has room. The original is untouched (volume backups).
TypeScriptimport { Runtime } from "withruntime";const runtime = new Runtime();const volume = await runtime.volumes.create({ sizeMiB: 10_240, name: "data" });const backup = await runtime.volumes.backup(volume.id, { retentionDays: 30 });const restored = await runtime.volumes.restore(backup.id, { name: "data-restored" });console.log(restored.id);Terminalruntime volume backup "${vol}" --retention-days 30runtime volume restore "${backup}" --name data-restoredOnly what changed since an earlier backup of the same volume is stored again. Deleting a volume keeps its backups until each one's retention ends.
Mistakes to avoid
- Letting the lease end on unsynced writes. Stopping a sandbox has it
write out its volumes first, but a sandbox whose lease runs out stops at
once. Run
syncafter writes it must keep. - Two writers. A read-write volume attaches to one sandbox at a time. For
many readers, attach it as
snapshot; for many writers, give each its own volume or mount a bucket. - Keeping work only on the sandbox's own disk. That disk has no copy off its server. Keep what you cannot rebuild on a volume.
- Oversizing. A volume is charged on its full size from creation, so a 100 GiB volume holding 2 GiB costs the same as a full one. Start near what you need.
- Expecting a snapshot to include the volume. A sandbox with volumes cannot be snapshotted. Snapshot a sandbox without volumes, and attach the volume to each copy you start.
Where volumes fit
A volume suits state that outlives a task: a per-user dev environment's home directory, a data analysis agent's datasets, or a package cache shared across runs. To keep a whole machine, memory included, between uses, pause it instead.
Facts on this page were checked on 25 September 2026.