Storage, volumes, snapshots
Scratch, persistent volumes, snapshot and restore, template distribution, and what each costs.
Four kinds of storage, with very different latency, durability and cost. Choosing wrongly between them is the second most common source of a surprising bill, after leaving sessions running.
| Kind | Backing | Latency | Durability | Lifetime | Meter |
|---|---|---|---|---|---|
| Scratch | Local NVMe | ~100 µs | None — lost with the host | Session | disk_gib_ms |
| Volume | Networked block, 3× replicated | ~500 µs | Survives host and zone-local failure | Independent | volume_gib_month |
| Snapshot | Object storage, compressed, encrypted | Seconds to restore | Regional, versioned | Until deleted | snapshot_gib_month |
| Template cache | Local NVMe, read-only shared | ~100 µs | Rebuildable | LRU | Not billed |
Scratch
Every session gets a local logical volume carved from the host's NVMe, mounted as the root overlay
and as /workspace when no volume is attached. It is fast, free of network variance, and destroyed
at teardown — discarded with a block-level trim, never reused without erasure.
Scratch is the right default. Most agent work is a clone, a build, a run and a result; none of it needs to outlive the session.
Volumes
A networked block device that outlives sessions.
# create
curl -sS "$WB_BASE_URL/volumes" -H "Authorization: Bearer $WB_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "name": "acme-monorepo", "size_gib": 50, "region": "bom1", "end_user_id": "eu_customer_4821" }'
# attach at session creation
curl -sS "$WB_BASE_URL/sessions" -H "Authorization: Bearer $WB_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "tier": 2, "volume_id": "vol_5Km3Xp", "mount_path": "/workspace" }'
Properties:
- One attachment at a time. Shared block storage across concurrent writers needs a cluster
filesystem, which is a different product. A second attach fails with
volume_in_use. - Zonal. A volume lives in one zone and constrains its session's placement to that zone. This is the most common cause of a warm-pool miss in an otherwise healthy region.
- Billed on provisioned size, always. A 50 GiB volume with no session attached still bills 50 GiB-months. Delete volumes you are not using.
- Resizable up, online. Shrinking requires creating a smaller volume and copying.
A volume is for an agent that keeps returning to the same working state — one customer's repository, one long-running project. A snapshot is for many sessions starting from the same prepared state. If you are cloning a volume to fan out, you want a snapshot.
Snapshots
A point-in-time image of a session: filesystem always, memory optionally for tiers 2 to 4.
curl -sS "$WB_BASE_URL/sessions/$SESSION/snapshot" \
-H "Authorization: Bearer $WB_API_KEY" -H "Content-Type: application/json" \
-d '{ "name": "deps-installed", "include_memory": true, "retention_days": 30 }'
{
"id": "snap_6Pq8Zt",
"session_id": "sess_2kQ9xwR4",
"tier": 2,
"include_memory": true,
"size_gib": 2.4,
"logical_size_gib": 11.8,
"state": "ready",
"created_at": "2026-10-06T09:31:12Z",
"expires_at": "2026-11-05T09:31:12Z"
}
How a snapshot is taken
1 freeze guest filesystem quiesced (fsfreeze), I/O drained
2 memory if include_memory: vCPUs paused, memory pages captured
— pause is typically 50–200 ms, visible to the workload
3 disk copy-on-write fork of the session's block device
4 thaw guest resumes; the session returns to running
5 upload dirty pages and CoW blocks streamed to object storage,
deduplicated against the base template, compressed, encrypted
6 ready snapshot becomes restorable
Steps 1 to 4 are the only time the workload is affected. Step 5 happens in the background against the frozen copy, so a large snapshot does not hold the session.
Deduplication
Snapshots are deduplicated against their base template and against earlier snapshots in the same
chain. A snapshot of a session that cloned a repository and installed dependencies typically stores
1–3 GiB of a 10–15 GiB logical filesystem. Billing is on size_gib — the stored, deduplicated,
compressed size — not the logical size.
Restore
curl -sS "$WB_BASE_URL/sessions" -H "Authorization: Bearer $WB_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "tier": 2, "restore_from": "snap_6Pq8Zt" }'
Restore latency depends on whether the snapshot's blocks are already in the target host's cache:
| Case | Tier 2 | Tier 4 |
|---|---|---|
| Blocks cached locally | ~300 ms | ~3 s |
| Cold read from object storage | 2–6 s, size-dependent | 8–25 s |
Frequently restored snapshots are promoted into regional block caches automatically. A snapshot attached to a warm pool is pre-materialised on every host in that pool.
With include_memory: true, the restored session resumes with running processes intact — a dev
server still listening, a REPL still holding state. The same two resume corrections as a pool
restore apply, and wbagent performs them before any workload runs: reseed the guest CSPRNG,
force a clock sync.
Cross-region copy
Snapshots are regional. Copying one to another region is explicit, billed as transfer, and subject to the organization's residency policy — a copy that would move data out of a restricted region is refused.
curl -sS "$WB_BASE_URL/snapshots/snap_6Pq8Zt/copy" \
-H "Authorization: Bearer $WB_API_KEY" -H "Content-Type: application/json" \
-d '{ "region": "fra1" }'
Template distribution
Templates are content-addressed and immutable, distributed as layers to a regional cache, then pulled onto hosts.
Two consequences for anyone publishing private templates:
- A freshly published template is cold until its pre-booted snapshots exist and have propagated. Publish ahead of the traffic that needs it.
- Host cache is LRU. A template used once a day is probably not resident, so it cold starts even when the fleet is healthy. Pin latency-critical templates to a warm pool.
Recordings
Tier 3 and tier 4 can record what they did: browser video, HAR files, CDP traces, desktop video.
Recordings go to object storage with a lifecycle policy, and are billed as recording_gib_month.
Recording defaults to off. A recording of a logged-in session can contain credentials, personal data and anything else that was on screen, so enabling it is a deliberate choice with an explicit retention period and an audit entry.
Encryption and residency
| Layer | Encryption |
|---|---|
| Scratch | Host-level full-disk encryption; per-session key for tier 4 |
| Volume | Encrypted at rest, per-organization key, optional customer-managed key |
| Snapshot | Encrypted at rest, per-organization key; copies re-encrypt per destination region |
| Recording | Encrypted at rest, per-organization key |
| In transit | TLS 1.3 everywhere, including host-to-storage |
Residency is enforced at the storage layer, not merely at placement. An organization pinned to
bom1 cannot have a volume, snapshot or recording materialise in another region, and a cross-region
copy request is refused rather than silently honoured.
Cost comparison
For a 20 GiB workspace an agent returns to a few times a day:
| Approach | Monthly cost shape |
|---|---|
| Keep a tier 2 session running | ~720 h × tier2.session_s — by far the most expensive |
| Keep a 20 GiB volume, start sessions on demand | 20 GiB-month + session time only when used |
| Snapshot after each use, restore on demand | ~3 GiB-month deduplicated + session time + restore latency |
The snapshot approach is usually an order of magnitude cheaper than the volume approach, which is itself two to three orders cheaper than holding a session open. The volume approach wins when the working set is large and restore latency matters more than storage cost.