On Runtime, a volume outlives the server it lives on. A volume is a disk that outlives sandboxes. It stays on one server, and it is copied off that server every day without a request from you. The copy is encrypted with a key that belongs to your organization alone. A restore can land on any server in the region. Backups are incremental. They cost $0.02 per decimal GB per 30-day month of what they store. A backup made before this price keeps $0.012 until 7 November 2026. For example, a week of daily backups that store 3 GB in all costs $0.06 a month (storage and backups).
Back up now
TypeScriptimport { Runtime } from "withruntime";const runtime = new Runtime();const volume = await runtime.volumes.create({ sizeMiB: 10_240, name: "data" });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", { check: true });const backup = await runtime.volumes.backup(volume.id, { retentionDays: 30 }); // waits up to a minuteconsole.log(backup.id, backup.state, backup.storedBytes);Pythonfrom withruntime import Runtimeruntime = Runtime()volume = runtime.volumes.create(10_240, name="data")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", check=True)backup = runtime.volumes.backup(volume["id"], retention_days=30)print(backup["id"], backup["state"])Terminalruntime volumes backup "${vol}" --retention-days 30 # prints the backup idruntime volumes backups "${vol}" # newest firstA backup is pending until its copy is written off the server, read back, and
checked. Then it is ready. The volume's backedUp turns true at that
point. backups.lastReadyAt shows when the newest backup was taken.
Restore it
A restore is always a new volume. It has the size of the backup, and it is created in the same region, on whichever server has room. The original is never changed:
TypeScriptimport { Runtime } from "withruntime";const runtime = new Runtime();const restored = await runtime.volumes.restore("<backup id>", { name: "data-restored" });console.log(restored.state, restored.restoredFrom); // "creating" until every byte is checkedawait using sbx = await runtime.sandboxes.create({ volumes: [{ volumeId: restored.id, path: "/data" }],});console.log((await sbx.exec("cat /data/note.txt")).stdout);Pythonfrom withruntime import Runtimeruntime = Runtime()restored = runtime.volumes.restore("<backup id>", name="data-restored")print(restored["state"], restored["restoredFrom"])Terminalruntime volumes restore "${backup}" --name data-restoredThe restored volume is ready once every byte has been downloaded and checked. Attach it to a new sandbox as you would any other volume.
Daily backups and how long they are kept
TypeScriptimport { Runtime } from "withruntime";const runtime = new Runtime();await runtime.volumes.setBackupPolicy("<volume id>", { daily: true, retentionDays: 14 });for await (const each of await runtime.volumes.backups({ volumeId: "<volume id>" })) console.log(each.id, each.trigger, each.readyAt, each.expiresAt);Terminalruntime volumes backup-policy "${vol}" --daily on --retention-days 14runtime volumes backup-rm "${backup}"Backups on your own schedule
A volume can be backed up every N minutes (15 or more), or on a five-field cron schedule in UTC. Keep its backups by count: the last N, and the newest in each of the newest N hours, days, weeks (from Monday), months and years. A backup that any count keeps is kept. The newest ready backup is also kept.
TypeScriptimport { Runtime } from "withruntime";const runtime = new Runtime();// Every hour; keep 24 hourly, 7 daily and 4 weekly backups.await runtime.volumes.setBackupPolicy("<volume id>", { schedule: { everyMinutes: 60 }, keep: { hourly: 24, daily: 7, weekly: 4 },});// 02:30 UTC on weekdays; back to daily with schedule: null.await runtime.volumes.setBackupPolicy("<volume id>", { schedule: { cron: "30 2 * * 1-5" } });await runtime.volumes.setBackupPolicy("<volume id>", { schedule: null });Terminalruntime volumes backup-policy "${vol}" --every 60 --keep hourly=24,daily=7,weekly=4runtime volumes backup-policy "${vol}" --cron "30 2 * * 1-5"runtime volumes backup-policy "${vol}" --no-scheduleThe volume reports its backups.schedule, keep and nextAt. A backup made on
the schedule has trigger: "scheduled". It has no expiresAt while the counts
keep it.
An agent does the same with the runtime_volumes_backup
MCP tool (create, list, get, policy, delete). It restores with
runtime_volumes, action create, and fromBackup.
The rules
| What | How it works |
|---|---|
| Daily backup | On for every volume, first taken an hour after it is created; daily: false turns it off |
| Your own schedule | Every 15 to 525,600 minutes from 1970-01-01 UTC, or a cron in UTC; replaces the daily backup until you set schedule: null |
| Retention | 7 days unless you set 1 to 365, per volume or per backup; on a schedule, the keep counts (each 0 to 1,000) |
| On request | backup(id) makes one now and waits up to a minute for it to be ready |
| What is stored | Only what changed since an earlier backup of the same volume; empty space not at all |
| Consistency | A point in time, as a disk is after a power cut |
| Encryption | Your organization's own data key; every piece is checked when read back |
| Deleting the volume | Its backups stay until each one's retention ends; a scheduled one stays the volume's retention days from then |
| Limit | 200 volume backups per organization at a time |
| Price | $0.02 per decimal GB per 30-day month ($0.012 until 7 November 2026 for one made before), on storedBytes, once the copy is ready |
The volume itself is charged on its full size, at 153 microdollars per GiB-hour, or about $0.11 per GiB a month. An account without credit keeps its first 10 GiB of volumes free (pricing).
Mistakes and how Runtime handles them
- Backing up in the middle of a write. A backup holds what the disk held at
that moment. It does not hold what a program still had in memory. For a clean
point, stop the sandbox first. A stop writes out what the sandbox wrote to its
volumes, and a stop that waits returns once the volumes are free. Otherwise,
run
syncor stop the database before you runbackup. - Running out of time or credit. Runtime freezes the sandbox's programs just before the end. It then writes out what they wrote to its volumes, as a stop does, at no charge.
- Losing the server. If a volume's server is lost, the volume goes with it. Its error names the newest backup to restore from.
- Expecting a restore to overwrite. A restore never overwrites anything. It
creates a new volume with
restoredFromset, so the damaged volume is still there to compare. - Snapshotting instead. A sandbox with volumes cannot be snapshotted. Back up the volume, and rebuild the sandbox from an image.
- Keeping data on the sandbox's own disk. A sandbox's disk has no copy off its server. Keep what you cannot rebuild on a volume.
Related
- Mount an S3 bucket for data that already lives in object storage.
- Pause and resume a sandbox to keep a whole machine, memory included.
- What is a sandbox snapshot?
Start
Terminalnpx withruntime volumes create --size-mib 1024 --name trial-dataA new account gets 100 free hours of a 1 GB machine in its first 30 days and 10 GiB of free volume storage, with no card. The first command prints a link to approve in your browser.
Facts on this page were checked on 26 October 2026.