Standby Disk
A standby disk is a storage volume prepared ahead of demand so a new machine can attach it and start work without downloading a machine image first.
A standby disk is a storage volume that was prepared ahead of demand and kept ready, so a new machine can attach it and begin work without downloading and unpacking a machine image first. The volume already carries an installed operating system, a filesystem that has completed its first boot, and whatever agent or toolchain the machine exists to run.
The term shows up wherever machines are created on demand and somebody is waiting for the first instruction to execute. In GitHub Actions that wait lands in the Set up job step, which runs before the first line of a workflow does anything useful.
Definition
A standby disk has three properties. Drop any one of them and the result is a different object.
- It carries a prepared filesystem. The operating system, the package set, the runtime versions, and any long-lived daemons are installed on the volume already. A machine attaching it starts from the state the image author intended rather than from a blank device.
- It exists before the request that consumes it. The volume is created and initialized on a schedule or by a background controller, so the work of materializing it sits outside the path a waiting job travels.
- It can be attached by a machine that does not exist yet. The volume is addressable independently of any one instance, either as the root volume of a stopped machine that can be powered back on or as a detached volume that a newly created instance binds at launch.
When no prepared volume is waiting, creating a machine runs a fixed sequence: allocate compute capacity, create a blank volume, copy the image contents into it, boot the operating system, run first-boot configuration such as cloud-init, attach networking, and start the agent. A standby disk moves the middle of that sequence ahead of the request, because the copy and the first boot are already finished when the request arrives.
| Startup work | Machine created from scratch | Machine started from a standby disk |
|---|---|---|
| Compute capacity allocated | At request time | At request time |
| Volume created | At request time | Already done |
| Image contents written to the volume | At request time | Already done |
| Operating system first boot | At request time | Already done |
| Network attachment and instance metadata | At request time | At request time |
| Agent start and registration | At request time | At request time |
Neighboring terms
Four terms in this area are routinely swapped for one another, and they describe different objects with different lifetimes.
| Term | What it is | Lifetime |
|---|---|---|
| Machine image | A template describing the disk contents a machine starts from | Indefinite, and one template serves many machines |
| Snapshot | A point-in-time copy of a volume, stored for restore or for cloning | Indefinite, until deleted |
| Standby disk | A live volume already materialized from a template and held ready to attach | Until it is attached, recycled, or deleted |
| Warm pool | A set of prepared machines or disks maintained at a target count | Maintained continuously by a controller |
A single standby disk is the unit. The warm pool is the accounting layer above it: a target count, a current count, and a reconciliation loop that creates replacements after disks are consumed.
The cost shape
Two states are used in practice. The first keeps the volume attached to a machine that has been stopped rather than terminated, which preserves the instance and its configuration alongside the disk. The second keeps the volume detached and attaches it to an instance created at request time.
AWS documents the billing consequence of the first form for EC2. Its instance state table marks pending, stopping, stopped, and shutting-down as not billed and running as billed, and the text states that you are not charged for usage or data transfer fees for an instance while it is stopped, while charges are incurred for the storage of any Amazon EBS volumes (Amazon EC2 instance lifecycle, checked on 2026-08-13). A prepared disk therefore bills as provisioned storage the whole time it waits, and as compute only during the initialization boot and during the job it eventually serves.
That split is why pool sizing tracks peak concurrent demand rather than total volume. Each waiting disk serves one machine at a time, so a workload with four jobs arriving together needs four prepared disks to cover all four, however many jobs the same fleet runs across a week.
Example
Take a self-hosted GitHub Actions fleet in a cloud account, running ephemeral runners. GitHub recommends implementing autoscaling with ephemeral self-hosted runners and advises against autoscaling with persistent ones, because GitHub assigns only one job to an ephemeral runner (self-hosted runners reference, checked on 2026-08-13). Every job in that model needs a machine that did not exist a moment earlier, which is exactly the case a standby disk addresses.
The workflow asks for the fleet by label and says nothing about disks:
name: test
on:
pull_request:
branches: [main]
jobs:
unit:
runs-on: [self-hosted, linux, x64]
strategy:
fail-fast: false
matrix:
shard: [1, 2, 3, 4]
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 22
- run: npm ci
- run: npx jest --shard=${{ matrix.shard }}/4A push to the pull request queues four jobs at once. With a pool of prepared disks in place, each of them travels this path:
- GitHub queues the job and holds it until an online runner advertises
self-hosted,linux, andx64. - The controller watching the queue claims one prepared disk from the pool.
- A machine attaches that disk and powers on. The operating system already finished first boot, so it reaches userspace without repeating installation or configuration work.
- The runner agent baked into the disk starts, registers against the repository or organization, and advertises its labels.
- GitHub sends the job to the newly registered runner.
Set up jobcompletes and the first workflow step runs. - The job finishes, the agent deregisters because it was configured with
--ephemeral, and the machine is destroyed. - The controller materializes a replacement disk so the pool returns to its target count.
The agent in step 4 is the open source runner published at github.com/actions/runner, and --ephemeral is a flag passed to its config.sh configuration step. Installing that agent on the disk before the job arrives is what allows step 4 to start immediately; a disk lacking it has to download and configure the agent while the job waits.
Two failure modes are worth naming, because both read as a broken feature from the run log.
An empty pool. When demand exceeds the prepared disks available, the fleet falls back to building a machine from scratch, and those jobs start at the uncached time. The jobs still run, so the symptom is a run where the first shards start promptly and the rest do not. The fix is a pool sized against peak concurrency, plus enough reconciliation headroom for the controller to refill between bursts.
A reused disk. A disk that has already served a job carries that job's leftovers: a populated package cache, a checked out repository, and any credentials a step wrote to the filesystem. Returning it to the pool as-is hands the next job a dirty machine and defeats the guarantee that ephemeral registration exists to provide. Consumed disks are rebuilt from the template instead of recycled in place.
Measuring the effect needs no instrumentation. Hold the workflow file constant, change the pool count, and compare the Set up job duration across a week of runs on that fleet. Every other number in the run stays where it was, since a standby disk changes when a job starts rather than what the job does.
Related Terms
- Standby disks for GitHub Actions runners in your own cloud account: how a prepared disk pool is sized and configured on runners that live in your own cloud account, including the spot instance constraint.
- Warm pool, the set of machines kept ready ahead of demand: the pool abstraction that maintains prepared machines or disks at a target count.
- Cold start, the startup work a prepared disk moves off the request path: the steps between a queued job and its first executed line, and which of them a prepared disk removes.
- WarpBuild standby disks documentation: the configuration surface for pool size, the instance state a waiting disk sits in, and the cost mechanics.
- WarpBuild BYOC documentation: connecting a cloud account and defining the custom runners a pool attaches to.
- Amazon EC2 instance lifecycle: the instance states, which of them are billed, and what a stopped instance retains.
- GitHub self-hosted runners reference: ephemeral registration, autoscaling guidance, and the queue behavior behind step 1.
- WarpBuild pricing: per minute rates by runner type.
FAQ
What is a standby disk?
A storage volume that was prepared before any request for it arrived and is held ready to be attached. It already carries an installed operating system, a filesystem that has completed first boot, and whatever agent the machine is meant to run, so a machine attaching it reaches userspace without repeating that work.
How does a standby disk differ from a machine image or a snapshot?
A machine image and a snapshot are templates held in storage and copied when something needs them. A standby disk is a live volume that was already materialized from one of those templates, so the copy step has finished and the volume is one attach operation away from running.
Does a standby disk cost money while nothing is running on it?
Provisioned storage is billed continuously, and compute is billed only while a machine is running. AWS documents this split for EC2: an instance in the stopped state is not billed for usage or data transfer, while charges are incurred for the storage of any Amazon EBS volumes.
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.