Skip to content

Platform Volumes

Platform volumes are named, persistent storage that the operator backs with shared cloud storage and you reference by name. Unlike external storage, you never supply a bucket URL or credentials — the operator configures one shared backend, and you just ask for a volume by name.

A platform volume:

  • has a name, scoped to your tenant;
  • persists across the sandbox lifecycle — it survives stop and destroy;
  • can be re-attached by the same name from a later sandbox and see the same data, on any node (it is backed by shared storage, not a host directory);
  • can be shared by multiple sandboxes.
External storagePlatform volume
Who owns the backendYou (your bucket + creds)The operator (shared bucket)
What you passsource + credentialsjust a name
LifetimeRemote data outlives the mountVolume persists, re-attach by name
ClusterWorks (you point at your store)Works — shared storage is the source of truth

Platform volumes must be enabled by the operator (see Operator setup). If they are not configured, every volume request is rejected with 412 Precondition Failed. Volumes are supported on the docker and gvisor runtimes only — firecracker and wasm reject them. Platform volumes count against the same per-sandbox cap as external mounts (8 total).

First use of a name creates the volume; reuse re-attaches the same data. The volume is mounted read-write by default.

const sandbox = await client.create({
image: 'ubuntu:22.04',
platformVolumes: [
{ name: 'data', path: '/workspace' },
],
})

Re-attach the same volume from another sandbox

Section titled “Re-attach the same volume from another sandbox”

Reference the same name from a second sandbox to see the data the first one wrote. Because the volume lives in shared storage, the second sandbox can land on a different node and still read it.

// First sandbox writes into the volume.
const a = await client.create({
image: 'ubuntu:22.04',
platformVolumes: [{ name: 'data', path: '/workspace' }],
})
// Later, a second sandbox mounts the same volume read-only.
const b = await client.create({
image: 'ubuntu:22.04',
platformVolumes: [{ name: 'data', path: '/workspace', readOnly: true }],
})
  • Persistence. Destroying a sandbox tears down the mount but never deletes the volume's data. Re-attach by name to get it back.
  • Naming. Names are lowercased and limited to [a-z0-9._-]; path separators and .. are rejected.
  • Tenant isolation. Volume names are scoped per tenant — two tenants using the name data get separate, isolated storage.
  • Quotas. Operators can cap the number of volumes per tenant; exceeding it returns a 409.
  • Concurrent writers. The default S3 backend is eventually consistent with no file locking — concurrent writers to the same volume can lose data. Use one writer plus read-only attachers, or coordinate at the application layer.
  • Cluster. Shared storage is the single source of truth, so a volume works no matter which node a sandbox is placed on. No node affinity is required.

Platform volumes are off by default. Enable them by pointing the daemon at a shared storage backend.

S3 (or any S3-compatible store such as Cloudflare R2 or MinIO):

SB_PLATFORM_VOLUMES_ENABLED=true
SB_PLATFORM_VOLUMES_BACKEND=s3
SB_PLATFORM_VOLUMES_S3_BUCKET=my-org-volumes
SB_PLATFORM_VOLUMES_S3_PREFIX=volumes # optional, default "volumes"
SB_PLATFORM_VOLUMES_S3_REGION=us-east-1
SB_PLATFORM_VOLUMES_S3_ENDPOINT= # optional, for R2/MinIO
SB_PLATFORM_VOLUMES_S3_ACCESS_KEY_ID=... # omit to use an instance role
SB_PLATFORM_VOLUMES_S3_SECRET_ACCESS_KEY=...
SB_PLATFORM_VOLUMES_MAX_PER_TENANT=0 # 0 = unlimited

NFS (a credential-free kernel mount against a shared export):

SB_PLATFORM_VOLUMES_ENABLED=true
SB_PLATFORM_VOLUMES_BACKEND=nfs
SB_PLATFORM_VOLUMES_NFS_SERVER=10.0.0.5
SB_PLATFORM_VOLUMES_NFS_EXPORT=/exports/volumes
SB_PLATFORM_VOLUMES_NFS_OPTIONS=vers=4.1 # optional

Gating:

ConditionBehavior
Disabled / unsetVolume APIs return 412
Enabled but misconfiguredDaemon fails fast at startup
Enabled + configuredVolumes attach normally

The operator owns and pays for the backing store, and is responsible for any storage-side lifecycle or retention policy. Operator credentials are sealed at rest, never returned by any read API, and never enter the sandbox — the mount runs on the host.