Skip to content

Drive snapshots and forks

A snapshot keeps a Drive as it was at one moment, as a version in its region's object store, without copying it. The Drive can be restored to it, a new Drive forked from it, and any number of sandboxes can mount it read-only.

Updated View as Markdown

A snapshot of a Drive keeps the Drive as it is at one moment. A Drive is copied into its region’s object store as it is written, and a snapshot is a version of it there: taking one copies nothing more, and neither does using one. From a snapshot you can:

  • restore the Drive to it, in place;
  • fork it: make a new Drive that holds what the snapshot holds, which can be mounted at once;
  • mount it read-only in any number of sandboxes at once, on any machine of the Drive’s region.

A snapshot outlives its Drive. After the Drive is deleted, its snapshots are still listed, forked and mounted read-only.

Every client has these calls: the command line (glac drives snapshots, glac drives fork, glac drives restore, glac drives attach --snapshot), the SDKs (Python and TypeScript below, and the Go, Rust and Java SDKs), the MCP server (drive_snapshot, drive_fork, drive_restore), and the console’s Drives page, where each Drive’s Snapshots are taken, forked, restored to and deleted.

The calls

Call What it does
POST /v1/drives/{id}/snapshots {name?, fs_consistent?} Takes a snapshot of the Drive now. Answers 201 with the snapshot.
GET /v1/drives/{id}/snapshots The Drive’s snapshots, newest first; a deleted Drive’s, by its id.
GET /v1/drive-snapshots The project’s snapshots of every Drive, newest first: where those of a Drive deleted since are found, with that Drive’s id. ?drive_deleted=true lists those alone, false the others (glac drives snapshots ls without a Drive).
GET, DELETE /v1/drives/{id}/snapshots/{snapshot} One snapshot, by its id; deletes it.
POST /v1/drives/{id}/restore {snapshot} Restores the Drive to the snapshot. Answers with the Drive.
POST /v1/drives/{id}/fork {name?, from_snapshot?} A new Drive made of the snapshot, or of the Drive as it is now. Answers 201 with the new Drive.
POST /v1/sandboxes/{id}/drives {drive, path, mode: "snapshot", snapshot} Mounts the snapshot read-only in a sandbox that exists. Answers with the snapshot.
POST /v1/sandboxes with drives: [{drive, path, mode: "snapshot", snapshot}] Mounts it read-only in a new sandbox.
DELETE /v1/sandboxes/{id}/drives/{snapshot} Takes the read-only mount away, by the snapshot’s id.

{id} is the Drive’s id or its name. Listing and reading snapshots takes a key with read; the other calls take write. The API reference has every field and answer of each call: take, list, read, delete, restore, fork, mount and take away.

A snapshot has an id (a dsnap-…), the drive_id of the Drive it is of, a name, its consistency (how the Drive’s writes were held for it: below), used_bytes (what the Drive held when it was taken), exclusive_bytes (what it keeps alone, which is what it is billed for) and exclusive_at (when that was last worked out), the version of the Drive it is (number, epoch), and created_at.

A name is optional: 1 to 63 lower-case letters, digits and hyphens, not starting or ending with a hyphen, and not starting with an id’s prefix such as vol- or dsnap- (400 invalid_name). Two snapshots may have the same name, so the calls name a snapshot by its id.

Taking a snapshot

In the examples, the Drive is data and a sandbox web has it at /data. glac drives snapshots create prints the snapshot’s id, kept here in SNAP:

SNAP=$(glac drives snapshots create data --name before-upgrade --fs-consistent)

A Drive is snapshotted whether a sandbox has it or not:

  • No running sandbox has it (it is not mounted, or the sandbox that has it sleeps): the snapshot is the Drive as it is (consistency: "at_rest").
  • A running sandbox has it: the snapshot is taken in two steps. First a version of what was written up to the call, while the sandbox goes on writing; then a version of what it wrote meanwhile, with its writes held. The hold lasts a fraction of a second for a sandbox that writes little, and ten seconds at the most: past that the snapshot is refused (503 unavailable, which can be retried) and the sandbox goes on. What is not in the object store yet is sent first, so a Drive that has just been written a lot takes longer.
  • How the writes are held: by default, the sandbox’s machine is paused (consistency: "paused"): the Drive is as it would be after a power cut, which its file system’s journal is for. With fs_consistent: true (--fs-consistent), the agent in the sandbox freezes the Drive’s file system instead ("frozen"): what the file system holds is written out first, and the snapshot mounts without replaying the journal. Where the agent cannot freeze it, the call is refused (409 not_frozen): take the snapshot without it.

List a Drive’s snapshots, read one, and delete one:

glac drives snapshots ls data                 # newest first: how each was taken, what it keeps alone
glac drives snapshots get data $SNAP
glac drives snapshots rm data $SNAP

A deleted snapshot is gone at once, and is billed up to that moment. The forks made of it keep what they need, and a sandbox that has it mounted read-only keeps the mount until it is taken away or the sandbox is deleted.

Restoring a Drive

A restore brings the Drive back to a snapshot: it then holds what it held when the snapshot was taken. It writes a new version after the Drive’s newest, whose content is the snapshot’s; nothing is copied, and the Drive keeps its id and name.

glac drives detach data web
glac drives restore data $SNAP
glac drives attach data web:/data
  • A Drive that a sandbox has read-write is not restored (409 drive_attached): detach it first, and attach it again after.
  • The versions in between stay where a snapshot or a fork keeps them: the Drive’s other snapshots, the ones taken after this one too, and its forks stay as they are, so a Drive restored to an older snapshot can then be restored to a newer one.
  • What the Drive held just before the restore is kept only where a snapshot keeps it: take one first if you may want to come back to it.
  • After a restore, the Drive’s blocks are fetched from the object store as they are read.

Forking a Drive

glac drives fork (POST /v1/drives/{id}/fork) makes a new Drive whose first version is the snapshot’s (--from-snapshot, from_snapshot) and prints its id. Without a snapshot, it is the Drive as it is now: a version is made for the fork as one is for a snapshot, and is not kept. Nothing is copied: the fork can be mounted at once, and its blocks come from the object store as they are read.

glac drives fork data --name data-try --from-snapshot $SNAP
glac sandboxes create --name try --drive data-try:/data
glac drives get data-try                      # with parent_drive_id (the id of data) and root_drive_id
  • A fork is a Drive like any other: it has an id and a name of its own, one sandbox writes it at a time, and it is billed and limited as a Drive. It has the size of the Drive it is made of, and is in that Drive’s region.
  • parent_drive_id is the Drive it was forked from, and root_drive_id the first Drive of its line of forks. Both are null for a Drive that is no fork.
  • What the fork writes is its own: the Drive and the snapshot do not change. Either may be deleted, and the fork keeps what it needs.
  • A snapshot of a deleted Drive is forked by the Drive’s id.
  • A fork’s name may not be another Drive’s or volume’s of the project (409 name_taken). A fork past the plan’s Drives is refused (403 drive_limit_reached), as a new Drive is.

Mounting a snapshot read-only

A read-only mount gives a sandbox the Drive as the snapshot has it, at a path. Any number of sandboxes can mount one snapshot at once, on any machine of the Drive’s region, whatever has the Drive: a sandbox may even have the Drive read-write and one of its snapshots read-only. A snapshot is mounted after its Drive is deleted, too.

glac drives attach data web:/then --snapshot $SNAP          # in a sandbox that runs
glac sandboxes exec web -- ls /then
glac drives detach $SNAP web                                # by the snapshot's id
glac sandboxes create --name reader --drive data:/then:dsnap-…   # in a new sandbox: the snapshot's id after the path
  • The Drive given (drive in the API) is the one the snapshot is of: its id or name, or a deleted Drive’s id. A snapshot of another Drive is refused (400 invalid_field).
  • A new sandbox mounts one with the same object in its drives (POST /v1/sandboxes; --drive DRIVE:/PATH:SNAPSHOT in the command line, since --snapshot there is the sandbox snapshot it goes on from). A read-only mount does not choose the machine the sandbox is made on, but it is made in the Drive’s region: a create that names another region, or Drives of two regions, is refused (409 not_on_one_machine).
  • A sandbox that runs on a machine of another region than the Drive’s is refused too (409 not_on_one_machine).
  • The file system is mounted read-only: the sandbox cannot write to it.
  • Its blocks come from the object store as the sandbox reads them, and are kept on the sandbox’s machine. Those fetched from the object store are billed to the sandbox’s account as Drive cold reads (below). The blocks kept count towards the share of that machine’s disk one account may hold: past it, the mount is refused (403 account_share_reached, which says how much).
  • It counts among the 8 Drives and volumes a sandbox mounts (409 too_many_drives).
  • It is not in the Drive’s attached_to, and it sends no drive.attached or drive.detached event.
  • It is taken away by the snapshot’s id: the Drive’s id or name takes away only a read-write mount (404 drive_not_attached). Deleting the sandbox takes it away too.

A sandbox’s snapshot and its Drives

A snapshot of a sandbox that has Drives read-write keeps each of them as a version, and copies nothing of them. A sandbox made from that snapshot gets a fork of each Drive, mounted at the same path, holding what the Drive held when the snapshot was taken. The Drive itself stays the first sandbox’s, and what it writes after does not reach the forks.

Each of these forks is a Drive of the project like any other: it is listed, its parent_drive_id is the Drive it was made of, it is billed by its used_bytes, and it is kept when the new sandbox is deleted, until you delete it.

From Python and TypeScript

from glac import DriveMount, Glac

glac = Glac()  # GLAC_API_KEY and GLAC_API_URL
drive = glac.drives.get("data")
web = glac.sandboxes.get("web")  # the sandbox that has it

snap = drive.snapshot(name="before-upgrade", fs_consistent=True)
for s in drive.snapshots():
    print(s.id, s.name, s.consistency, s.exclusive_bytes)

# a new Drive made of the snapshot, in a new sandbox
fork = glac.drives.fork(drive, name="data-try", from_snapshot=snap)
trial = glac.sandboxes.create(drives=[DriveMount("/data", fork)])

# the snapshot, read-only: in a new sandbox, and in one that runs
reader = glac.sandboxes.create(drives=[DriveMount("/then", drive, snapshot=snap)])
glac.drives.attach_snapshot(trial, snap, "/then")
print(trial.run("ls /then").stdout)
glac.drives.detach_snapshot(trial, snap)

# the Drive back to the snapshot, while no sandbox has it read-write
glac.drives.detach(web, drive)
glac.drives.restore(drive, snap)
glac.drives.attach(web, drive, "/data")

snap.delete()
import { Glac } from "glac";

const glac = new Glac();                                    // GLAC_API_KEY and GLAC_API_URL
const drive = await glac.drives.get("data");
const web = await glac.sandboxes.get("web");                // the sandbox that has it

const snap = await drive.snapshot({ name: "before-upgrade", fsConsistent: true });
for (const s of await drive.snapshots()) console.log(s.id, s.name, s.consistency, s.exclusiveBytes);

// a new Drive made of the snapshot, in a new sandbox
const fork = await glac.drives.fork(drive, { name: "data-try", fromSnapshot: snap });
const trial = await glac.sandboxes.create({ drives: [{ path: "/data", drive: fork.id }] });

// the snapshot, read-only: in a new sandbox, and in one that runs
const reader = await glac.sandboxes.create({ drives: [{ path: "/then", drive: drive.id, snapshot: snap }] });
await glac.drives.attachSnapshot(trial, snap, "/then");
console.log((await trial.run("ls /then")).stdout);
await glac.drives.detachSnapshot(trial, snap);

// the Drive back to the snapshot, while no sandbox has it read-write
await glac.drives.detach(web, drive);
await glac.drives.restore(drive, snap);
await glac.drives.attach(web, drive, "/data");

await snap.delete();

A snapshot is a DriveSnapshot in both, with refresh, fork, restore, attach, detach and delete of its own. attach mounts a Drive read-write: a snapshot is mounted read-only with attach_snapshot (attachSnapshot), or with a snapshot in a new sandbox’s drives. See the Python and TypeScript SDK pages for every call.

With the command line

Command What it does
glac drives snapshots create DRIVE [--name NAME] [--fs-consistent] Takes a snapshot and prints its id.
glac drives snapshots ls DRIVE, get DRIVE SNAPSHOT, rm DRIVE SNAPSHOT… A Drive’s snapshots, newest first; one; deletes them. A deleted Drive’s, by its id.
glac drives restore DRIVE SNAPSHOT Takes the Drive back to the snapshot.
glac drives fork DRIVE [--name NAME] [--from-snapshot SNAPSHOT] A new Drive made of the snapshot, or of the Drive as it is now; prints its id.
glac drives attach DRIVE SANDBOX:/PATH --snapshot SNAPSHOT, glac drives detach SNAPSHOT SANDBOX Mounts the snapshot read-only in a sandbox that runs; takes it away.
glac sandboxes create --drive DRIVE:/PATH:SNAPSHOT A new sandbox with the snapshot mounted read-only.
glac drives get DRIVE A fork’s parent_drive_id and root_drive_id, with the rest of the Drive.
glac usage --snapshot SNAPSHOT What one snapshot has kept.

What is billed

  • A snapshot is billed for what it keeps alone (exclusive_bytes): the data its version needs that the Drive as it is now, its newer snapshots and its forks do not. Data that two snapshots keep is counted on the older one. A snapshot of a Drive that has not changed since keeps nothing alone. After the Drive is deleted, what it held is counted on its snapshots.
  • It is billed hour by hour at $0.02 a GB-month, on the storage meter with what Drives hold, from the first time what it keeps alone is worked out (exclusive_at) until it is deleted. Free’s 15 GB of storage and Paid’s 20 GB-months cover snapshots with Drives and sleeping sandboxes. See pricing and plans.
  • GET /v1/usage?snapshot_id=dsnap-… reports what one snapshot has kept, and so does glac usage --snapshot dsnap-….
  • A fork is a Drive, and is billed as one, by its used_bytes: everything it holds as you read it, including the data it shares with the snapshot it was made from. A fork of a snapshot of a Drive holding 10 GB is billed as a 10 GB Drive from the start, though most of its blocks are shared underneath. Its NVMe cache is billed as for any Drive; what is written to it and read from it costs nothing. See how Drives work.
  • A read-only mount: the blocks fetched from tiered storage for it cost nothing, and two sandboxes that mount one snapshot each read it for nothing. The blocks it keeps on the machine are a cache of the snapshot, which is billed as above.

When an account owes or is held back

  • An account in debt can list, read and delete its Drives’ snapshots, so that what it owes stops growing. It cannot take snapshots, fork, restore or mount (402 account_in_debt). If it still owes 30 days after the first email, everything it stores is deleted, its snapshots among it (drive.snapshot.deleted). See an account that owes.
  • A project that its spend limit holds back, or whose account has used what its plan includes and has no balance, takes no snapshots and makes no forks (403 spend_limit_reached, balance_used_up). What its snapshots keep goes on being counted. Cold reads through read-only mounts are cold reads like any other: when they have used what the plan includes and the balance is empty, the account’s sandboxes stop as they do for any Drive’s (when a meter runs out).

Limits and errors

  • A Drive may have any number of snapshots; each is billed for what it keeps alone. Snapshots are not counted among the project’s Drives.
  • A fork is counted as a new Drive of its size: see what a project may keep.
  • A read-only mount counts among the 8 Drives and volumes of a sandbox.
Answer When
400 invalid_name A name that is not 1 to 63 lower-case letters, digits and hyphens, or that starts with an id’s prefix.
400 missing_field A restore without snapshot; a mount with mode: "snapshot" and no snapshot.
400 invalid_field snapshot names a snapshot of another Drive, or is given without mode: "snapshot".
402 account_in_debt Anything but listing, reading and deleting, while the account owes.
403 drive_limit_reached A fork past the Drives the plan lets the project keep.
403 spend_limit_reached, balance_used_up A snapshot or a fork while the project is held back.
403 account_share_reached A fork, a restore or a read-only mount on a machine where the account already holds as much of the disk as one account may. The message says how much.
404 drive_not_found, snapshot_not_found No Drive of that id or name, or no snapshot of that id of the Drive. A deleted Drive’s snapshots are reached by the Drive’s id.
404 drive_not_attached A read-only mount taken away by the Drive’s id or name instead of the snapshot’s id, or one the sandbox does not have.
409 drive_attached A restore while a sandbox has the Drive read-write.
409 not_frozen fs_consistent: true, and the agent in the sandbox could not freeze the file system.
409 name_taken A fork’s name is another Drive’s or volume’s.
409 not_on_one_machine A read-only mount in a sandbox of another region than the Drive’s, or a new sandbox whose region is not its Drives’.
409 too_many_drives The sandbox has 8 Drives and volumes already.
503 unavailable The version could not be made now: the sandbox’s writes were not read within the ten seconds of the hold, or the object store does not hold the Drive as it is yet. Ask again in a moment.
503 drive_in_store No machine holds the Drive at this moment: it is on its way to another. Ask again in a moment.
503 node_unavailable The machine that holds the Drive cannot be reached.

Events

drive.snapshot.created and drive.snapshot.deleted come in the project’s events and webhooks, with snapshot_id, drive_id, name and consistency. A snapshot deleted because its account did not pay sends drive.snapshot.deleted too. A read-only mount, and taking it away, send no drive.attached or drive.detached.

Not there yet

  • A Cube’s version mounts its Drives read-write only: a version with mode: "snapshot" is refused (400 invalid_field). Read-only mounts are for sandboxes.
  • A sandbox that has a read-only mount cannot move to another machine.
  • Sandboxes on one machine that mount the same snapshot each keep its blocks: they do not share them.
  • The forks a sandbox made from a sandbox snapshot gets are not checked against the plan’s Drive limits when it is made; they count from then on.
  • A snapshot is mounted read-only in the region it was taken in only (the Drive itself is mounted in another region too: across regions). A snapshot of a deleted Drive has no region the platform knows: it is mounted where the sandbox is made, and a machine that copies to another region’s object store refuses it.
Navigation

Type to search…

↑↓ navigate↵ selectEsc close