On this page

A Volume is a persistent block device attached to a runtime instance. Survives instance restarts and version promotions. Useful for:

  • SQLite databases that need to be local to the runtime.
  • Caches you can’t afford to lose on restart.
  • LLM model weights downloaded once and shared across instances.
  • Workloads that legitimately need filesystem state (not just key-value).

Volumes are NOT useful for:

  • Stateful databases - use Postgres instead. It scales better, backs up automatically, and survives host failures.
  • User-uploaded files - use Storage / Buckets. Cheaper, browser-uploadable, geo-replicable.
  • Shared state across multiple replicas - volumes are typically attached to ONE runtime instance.

Create

Use it your way — API, CLI, or SDK

No SDK required.

Raw API (curl): the raw API takes size_bytes and a backend (use local).

# Create a 50 GB volume
curl -X POST https://api.miosa.ai/api/v1/volumes 
  -H "Authorization: Bearer $MIOSA_API_KEY" -H "Content-Type: application/json" 
  -d '{"name": "model-weights", "size_bytes": 53687091200, "backend": "local"}'

# Attach it to a running computer at a mount path
curl -X POST https://api.miosa.ai/api/v1/computers/COMPUTER_ID/volumes 
  -H "Authorization: Bearer $MIOSA_API_KEY" -H "Content-Type: application/json" 
  -d '{"volume_id": "VOL_ID", "mount_path": "/mnt/data"}'

# Detach (by attachment id)
curl -X DELETE https://api.miosa.ai/api/v1/computers/COMPUTER_ID/volumes/ATTACHMENT_ID 
  -H "Authorization: Bearer $MIOSA_API_KEY"

CLI:

miosa volumes create model-weights --size 50
miosa volumes list
miosa volumes attach <id>
miosa volumes detach <attachment-id>
miosa volumes destroy <id>

A local-backend volume lives on one host, so it attaches to computers on that same host. Cross-host attach returns a clear error rather than failing silently.

Mount

A volume is mounted into the runtime instance’s filesystem at a path:

await miosa.services.update(serviceId, {
  volumes: [
    { dataServiceId: volumeId, mountPath: "/var/models" },
  ],
})

At boot, /var/models is the volume’s contents. Writes persist.

Replicas and volumes

Most volumes attach to a single runtime instance. If you scale a service to N replicas, by default each replica gets the same volume mount if it’s marked shared: true, or its own volume if shared: false.

Shared volumes have all the usual concurrency caveats (filesystem locks, file-corruption risk if multiple writers touch the same file). Use Postgres for shared state unless you really know what you’re doing.

Snapshots and backups

Volumes can be snapshotted on a schedule. Snapshots are point-in-time, immutable, restorable. Configure via:

await miosa.projects.dataServices.update(volumeId, {
  snapshot_schedule: "0 4 * * *",  // daily at 4am UTC
  snapshot_retention_days: 7,
})

Limits

LimitDefault
Max volume size500 GB
Max volumes per project10
Filesystemext4
Backup retentionper schedule, default 7 days

When to use a volume

Realistic short list:

  1. You’re shipping a self-hosted SQLite-backed app to keep deployment simple.
  2. You’re running an LLM inference service and don’t want to re-download model weights on every instance start.
  3. You have a writable filesystem cache that’s expensive to rebuild.

Anything else, use Postgres or Storage.

See also

  • Overview - the broader data plane
  • Postgres - for relational data (almost always the right answer)
  • Storage - for user-uploaded files

Was this helpful?