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.

  1. 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.
  2. 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.
  3. 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 workMachine created from scratchMachine started from a standby disk
Compute capacity allocatedAt request timeAt request time
Volume createdAt request timeAlready done
Image contents written to the volumeAt request timeAlready done
Operating system first bootAt request timeAlready done
Network attachment and instance metadataAt request timeAt request time
Agent start and registrationAt request timeAt request time

Neighboring terms

Four terms in this area are routinely swapped for one another, and they describe different objects with different lifetimes.

TermWhat it isLifetime
Machine imageA template describing the disk contents a machine starts fromIndefinite, and one template serves many machines
SnapshotA point-in-time copy of a volume, stored for restore or for cloningIndefinite, until deleted
Standby diskA live volume already materialized from a template and held ready to attachUntil it is attached, recycled, or deleted
Warm poolA set of prepared machines or disks maintained at a target countMaintained 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 }}/4

A push to the pull request queues four jobs at once. With a pool of prepared disks in place, each of them travels this path:

  1. GitHub queues the job and holds it until an online runner advertises self-hosted, linux, and x64.
  2. The controller watching the queue claims one prepared disk from the pool.
  3. 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.
  4. The runner agent baked into the disk starts, registers against the repository or organization, and advertises its labels.
  5. GitHub sends the job to the newly registered runner. Set up job completes and the first workflow step runs.
  6. The job finishes, the agent deregisters because it was configured with --ephemeral, and the machine is destroyed.
  7. 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.

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.