VM Snapshot

A VM snapshot is a saved copy of a virtual machine's disk at a point in time. What it captures, what it drops at boot, and how a job boots from one.

A VM snapshot is a saved copy of a virtual machine's disk, and in some implementations its memory and CPU state, recorded at one point in time. A machine started later from that copy comes up with the filesystem exactly as it stood at capture, so the work already done on that disk is present before the first command runs.

In GitHub Actions the appeal is direct. A job that installs the same dependency tree on every run repeats work that a previous machine already finished, and a snapshot lets a later job begin from a machine where that work has already happened.

Definition

A virtual machine reads and writes a virtual disk, which the hypervisor backs with a file or a block device. A snapshot records the contents of that disk at an instant. The record can be a full copy of every block, though implementations more often store a pointer to an earlier copy plus the blocks that changed since it, which is why the second snapshot of a machine is usually far smaller than the first.

Most systems capture the disk without pausing the machine, using copy-on-write. Once the capture starts, new writes go to a fresh layer while the frozen blocks stay readable, so the snapshot is consistent with the disk at the instant it began rather than with the disk as it looks when the capture finishes. Snapshots therefore form a chain: a base image, then a delta, then another delta, each one readable only alongside the layers beneath it.

Two kinds of capture exist, and the difference decides what a restored machine can do.

A disk-only snapshot records the virtual disk alone. Restoring it is equivalent to cutting power to the machine and booting the saved disk, which is why this kind is described as crash consistent: a file half written when the capture ran is half written in the snapshot. Block storage snapshots from the major clouds work this way, including Amazon EBS snapshots and Google Compute Engine disk snapshots (checked on 2026-08-13).

A full state snapshot adds the contents of RAM, the CPU registers, and virtual device state. A machine restored from one resumes mid-instruction with its processes still running. This kind is common in desktop hypervisors and in live migration, and it is rare in build infrastructure because the captured memory is large and a resumed process holds stale network connections.

The practical consequence for a build machine is a short list of what survives a disk-only capture.

State on the machinePresent after booting the snapshotWhy
Installed system packages and language toolchainsYesWritten to the filesystem the snapshot recorded
Dependency directories such as node_modules, vendor/, and ~/.cargoYesOrdinary files on the captured disk
Package manager caches under $HOMEYesOrdinary files on the captured disk
A git working tree and its .git directoryYesOrdinary files on the captured disk
Container images already pulled into the local image storeYesStored on disk by the container runtime
Files written under /tmpNo, on systems that clear it at bootA restore is a boot, and the clear runs again
Running processes, listening ports, and started containersNoA disk-only capture holds no process state
Contents of RAM, including a database page cacheNoMemory is outside a disk-only capture
Hostname, MAC address, and cloud instance metadataNoAssigned fresh to the new machine at boot

Four neighboring terms get used interchangeably and should not be.

  • Image. A prepared disk built by a pipeline and published as a versioned artifact for many machines to boot from. A snapshot is captured from one running machine rather than built from a definition, and it is usually short lived.
  • Backup. An independent copy stored elsewhere on a retention schedule, sized to survive the loss of the original storage. A snapshot chained to a live disk does not meet that bar.
  • Checkpoint. A full state capture taken so execution can resume from the same instant. Every checkpoint is a snapshot; most snapshots are disk-only and are not checkpoints.
  • Clone. A new machine created from a snapshot or an image. The snapshot is the record; the clone is the machine that reads it.

Because a snapshot occupies storage for as long as it is kept, providers charge for it by time and expire it on a retention window. That turns the interesting question from whether a snapshot can be taken into how often it should be refreshed and how long the captured state stays close enough to the current commit to be worth booting.

Example

The pattern in GitHub Actions is a capture after the expensive preparation step, followed by later jobs that boot from the captured disk. This workflow installs a dependency tree, builds, tests, removes credentials, then captures the machine under an alias:

name: build
on:
  push:
    branches: [main]

jobs:
  build:
    runs-on: warp-ubuntu-latest-x64-2x;snapshot.key=web-deps
    steps:
      - uses: actions/checkout@v5
      - run: npm ci
      - run: npm run build
      - run: npm test
      - name: Remove credentials before capture
        run: |
          rm -rf $HOME/.ssh $HOME/.aws
          git clean -ffdx
      - uses: WarpBuilds/snapshot-save@v1
        with:
          alias: web-deps

The label suffix and the capture action follow the syntax in the snapshot runners documentation, checked on 2026-08-13.

The first run finds no saved disk for the alias web-deps, so the machine boots the base image and every step does its full work. The final step captures the disk after npm ci has populated ~/.npm and node_modules, and after the checkout has written the .git directory into the workspace. The next run boots that captured disk, so the machine reaches its first step with the state below already in place.

At the first stepMachine booted from the base imageMachine booted from the snapshot
node_modulesAbsentPresent as captured
~/.npm package cacheEmptyPopulated from the earlier install
.git objects in the workspaceAbsentPresent from the earlier checkout
Container images pulled by an earlier jobAbsentPresent in the local image store
Scratch files under /tmpAbsentAbsent, cleared during boot
A database started by an earlier jobAbsentAbsent, no process survives the capture

Two details decide whether the pattern holds up. The capture takes whatever is on disk, so an SSH key or a cloud credential file written during the job lands in the saved copy and reaches every machine that later boots it, which is what the cleanup step above removes. And the captured tree ages against the repository: once a lockfile changes, the versions the install step asks for sit outside the captured cache and the step fetches them again, so a stale alias quietly stops helping and needs a fresh capture.

FAQ

What is the difference between a VM snapshot and a backup?

A snapshot is a point-in-time record of a virtual disk that usually lives beside the disk it came from and often depends on earlier blocks in a chain. A backup is an independent copy held somewhere else, kept on a retention schedule, and designed to survive the loss of the original storage. A snapshot restores a machine quickly; a backup survives the failure of the system that held the machine.

Does a VM snapshot include the contents of memory?

Only when the implementation captures machine state as well as disk. Block storage snapshots from cloud providers record the virtual disk alone, so a machine that boots from one comes up as though it had been powered off and started again. Running processes, listening ports, page caches, and anything held only in RAM are gone, and any service the job needs has to be started again.

Why does a job still reinstall dependencies after booting from a snapshot?

The snapshot holds the filesystem as it was at capture time, so an install step still runs and still checks its inputs. What changes is where the bytes come from: a populated package manager cache on the restored disk answers the request locally instead of over the network. A lockfile change after the capture puts the requested versions outside the captured cache, and the step goes back to fetching them.

Start with $10 in free credits

Change the runner label in your workflow and keep the rest of your GitHub Actions setup. Runner time is billed per minute.