Skip to content
Fuse
Esc
navigateopen⌘Jpreview
On this page

Snapshots

Capturing and restoring a running microVM's state

client.Snapshots captures and restores the state of a running microVM. Take a snapshot before something risky, and restore if it goes wrong:

snap, err := client.Snapshots.Create(ctx, env.ID, fuse.SnapshotRequest{
	Comment: "before risky migration",
	Mode:    "manual",
})
if err != nil {
	log.Fatal(err)
}

// ... do the risky thing ...

if err := client.Snapshots.Restore(ctx, snap.ID); err != nil {
	log.Fatal(err)
}
  • Create’s vmID must be a running environment. SnapshotRequest is entirely optional, a zero-value struct is a valid request; Mode is "manual" or "auto", and RetentionSeconds of 0 keeps it forever.
  • Restore is in place only: it restores onto the snapshot’s original VM, which must still be running. There is no cross-host restore, clone, or standalone restore into a new VM, use Fork on EnvironmentsService for that instead.

Live snapshots

SnapshotRequest.Live opts into capturing the guest’s memory and vCPU state alongside the disk. The zero value is a disk-only snapshot, which is the default and the fallback:

snap, err := client.Snapshots.Create(ctx, env.ID, fuse.SnapshotRequest{
	Comment: "warmed model loaded",
	Live:    true,
})
if err != nil {
	log.Fatal(err)
}
// snap.Kind is "live" here, "disk" on every other snapshot

Snapshot.Kind is "live" or "disk" and is set by the host agent, not by the caller reading its own request back. Restore has no Live counterpart: it reads the kind off the snapshot and either resumes the guest or cold-boots it.

The trade-offs are the same ones documented under Snapshots, and they are sharp enough to repeat:

  • Snapshot.SizeBytes on a live snapshot includes a full copy of the environment’s configured memory, on every create. Tenant byte quotas were calibrated for rootfs-only snapshots, so a Create loop with Live: true will hit 409 conflict on quota much sooner than the snapshot count implies.
  • the guest is paused for the duration of the capture.
  • a live snapshot cannot seed a new environment. Environments.Fork and CreateRequest.SeedSnapshotID read only a snapshot’s rootfs, and a live snapshot’s rootfs is captured without quiescing the guest filesystem, so it mounts cleanly only alongside its memory image. Both reject one with 409 conflict. Take a disk snapshot when you want a copy rather than a rewind.
  • a live snapshot is pinned to the host that took it. The memory image depends on that host’s CPU model and Firecracker version.

Live: true against a backend with no live-snapshot support returns 501 unimplemented, not a conflict, so fuse.IsConflict(err) does not match it. The message says to retry without live for a disk snapshot.

Snapshot.Kind is worth checking rather than assuming: a host running an agent too old to know about live snapshots answers Live: true with a disk snapshot, and the record then says "disk". Recording the request rather than the result would file a cold-booting artifact as a resumable one.

Everything else

Method Purpose
List(ctx, ListSnapshotsOptions{...}) List snapshots, optionally filtered by VMID/TaskID/TenantID/State.
Get(ctx, snapshotID) Fetch one snapshot’s full detail, including State (creating|ready|restoring|deleting|error), Kind (disk|live), and Exports.
Delete(ctx, snapshotID) Leaf-only delete; also removes the underlying provider artifact. No soft-delete.

These mirror the HTTP API one to one.

The QEMU/GPU exception

Environments running on the QEMU backend (whole-GPU passthrough) cannot be snapshotted or forked at all, Snapshots.Create and Environments.Fork against a GPU environment fail with a 409 conflict *APIError rather than silently no-op-ing. Restore carries no GPU check of its own, it is simply unreachable for a GPU environment because no snapshot of one can exist. See Providers.

fuse.IsConflict(err) reports true for the GPU guardrail, so branch on that rather than on the error message. A backend with no snapshot support at all returns 501 unimplemented instead, which IsConflict does not match.

Was this page helpful?