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 machine | Present after booting the snapshot | Why |
|---|---|---|
| Installed system packages and language toolchains | Yes | Written to the filesystem the snapshot recorded |
Dependency directories such as node_modules, vendor/, and ~/.cargo | Yes | Ordinary files on the captured disk |
Package manager caches under $HOME | Yes | Ordinary files on the captured disk |
A git working tree and its .git directory | Yes | Ordinary files on the captured disk |
| Container images already pulled into the local image store | Yes | Stored on disk by the container runtime |
Files written under /tmp | No, on systems that clear it at boot | A restore is a boot, and the clear runs again |
| Running processes, listening ports, and started containers | No | A disk-only capture holds no process state |
| Contents of RAM, including a database page cache | No | Memory is outside a disk-only capture |
| Hostname, MAC address, and cloud instance metadata | No | Assigned 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-depsThe 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 step | Machine booted from the base image | Machine booted from the snapshot |
|---|---|---|
node_modules | Absent | Present as captured |
~/.npm package cache | Empty | Populated from the earlier install |
.git objects in the workspace | Absent | Present from the earlier checkout |
| Container images pulled by an earlier job | Absent | Present in the local image store |
Scratch files under /tmp | Absent | Absent, cleared during boot |
| A database started by an earlier job | Absent | Absent, 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.
Related Terms
- Snapshot runners and the label options that select them: the
snapshot.enabledandsnapshot.keylabel suffixes, the platforms that accept them, and the retention window. - What carries over in a runner snapshot: the state a later job finds on disk and the state it has to rebuild.
- Warm caches and what keeps a cache warm between jobs: the broader idea a snapshot is one implementation of.
- Snapshot runners documentation: capture syntax, cleanup guidance, and the supported platforms.
- Cloud runners documentation: the runner labels a workflow can point
runs-onat. - WarpBuild pricing: per minute rates by runner type.
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.