Standby Disks for BYOC GitHub Actions Runners

Standby disks keep BYOC GitHub Actions runners warm by holding pre-initialized VMs shut down, so a queued job starts in about 15 seconds. Setup and cost.

Last verified:

Overview

Standby disks keep BYOC GitHub Actions runners warm by holding a pool of pre-initialized VMs of the same instance type as the runner, each booted once and then shut down without being terminated. When GitHub queues a job, WarpBuild powers one of those VMs back on and the job starts in about 15 seconds, per the standby disks documentation.

The feature has one configuration value, the pool size per custom runner, and it requires no workflow change. The runs-on label stays the same, the job steps stay the same, and the difference shows up in the Set up job duration in the GitHub Actions log.

Standby disks address the front of the job only: runner allocation and machine boot. Toolchain installs, dependency restores, and first-run compilation are untouched, and those are handled by caching and by the levers covered in the guide to removing cold starts from GitHub Actions jobs.

Four facts decide whether the feature fits your fleet:

  • WarpBuild does not charge for standby disks. Your cloud account carries the VM initialization time and the disk.
  • Spot instances are not supported for standby disks.
  • The pool is per custom runner, so a runner type with 24-way test fan-out and a runner type with one deploy job are sized separately.
  • An empty pool costs you speed alone. WarpBuild creates a fresh VM for the job, which starts at the normal time.

Standby disks are a BYOC feature. BYOC runs on AWS, GCP, and Azure, and the setup path for each cloud is in the BYOC documentation. The AWS specifics, including instance selection and quotas, are on the AWS BYOC page.

How It Works

A standby disk is a VM of the same type as the runner that is immediately shut down after boot up. That boot does real work: it initializes the VM, sets up networking, and applies the other machine configuration a runner needs before it can accept a job. Shutting the instance down puts it into a shutdown state without terminating it, so the initialized state survives on the network disk.

When GitHub requests a runner, the WarpBuild control plane checks whether a standby disk is available for that custom runner:

  1. A disk is available. It is powered on and allocated to the job, and the job starts in about 15 seconds.
  2. No disk is available. A new VM is created and allocated to the job, and the job starts at the normal BYOC provisioning time.

The control plane maintains the pool in the background, within reconciliation time limits of about a minute. A burst that drains an eight-disk pool is refilled on that timescale, which is why the sizing question is about peak concurrency rather than daily job volume. Jobs arriving during that refill window fall into case 2 and still run.

Instance type selection follows the runner configuration exactly. The instance type of a standby disk is the same as the runner type, and where a custom runner lists fallback instance types, the standby disk will be one of those multiple instance types. A runner configured with m7a.xlarge and m7i.xlarge in priority order can therefore hold a pool of either shape, which is one more reason to choose fallback types with similar performance.

Constraints worth reading before you enable it

ConstraintDocumented behavior
Spot instancesNot supported for standby disks. Spot instances may be terminated at any time and it cannot be guaranteed that a standby instance will be available.
Fallback instance typesThe standby disk is one of the instance types selected on the runner, so a mixed fallback list produces a mixed pool.
Empty poolA new VM is created for the job. The job runs, and it starts at the normal provisioning time.
Pool refillHandled by the WarpBuild control plane within reconciliation time limits of about a minute.
Instance stateThe VM is put into a shutdown state and is never terminated, so the initialized disk persists.
WarpBuild chargeNone. WarpBuild does not charge for standby disks.

The spot constraint is the one that changes plans. Spot capacity and standby pools are mutually exclusive on the same custom runner, so a fleet that wants both ends up splitting runner types: on-demand types with standby pools for the interactive, pull request path, and spot types for long batch jobs where a reclaim and a retry cost less than the discount is worth. AWS states that Spot Instances run at up to a 90 percent discount compared to On-Demand prices (AWS EC2 Spot Instances, checked on 2026-08-13), and that trade is worked through in the guide to spot instances for GitHub Actions runners.

Configuration

The number of standby disks is configurable per custom runner. Set it in the custom runners view of the WarpBuild dashboard on the runner you want to start quickly, and choose the number of standby disks based on the number of jobs you expect to run concurrently for that runner type.

Size the pool from peak concurrency rather than from weekly volume. A repository that runs 2,000 jobs a week but never more than four at once on a given runner type needs four disks, and a repository that runs 300 jobs a week in bursts of 24 needs 24.

Workflow shape on one runner typePeak concurrent jobsPool sizeWhat the overflow gets
One build job per pull request, 6 open pull requests66Nothing overflows
8-way sharded test matrix, 3 pull requests in flight2424Nothing overflows
8-way sharded test matrix, sized at 824816 jobs start at normal provisioning time
Nightly batch of 40 jobs, no interactive wait400All 40 start at normal provisioning time

The last row is deliberate. A pool that exists for a nightly batch pays for disks all day to save seconds nobody is waiting on, so leave those runner types at zero and spend the pool on the runner types that gate a code review.

Referencing the runner in a workflow

A BYOC runner is addressed by its Runner ID, which is the runner name prefixed with warp-custom-. Enabling standby disks changes nothing in this file:

.github/workflows/test.yml
name: test

on:
  pull_request:
    branches: [main]

jobs:
  lint:
    runs-on: warp-ubuntu-latest-x64-2x
    steps:
      - uses: actions/checkout@v4
      - run: npm ci
      - run: npm run lint

  unit:
    runs-on: warp-custom-linux-x64-8x
    strategy:
      fail-fast: false
      matrix:
        shard: [1, 2, 3, 4, 5, 6, 7, 8]
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: 22
          cache: npm
      - run: npm ci
      - run: npx jest --shard=${{ matrix.shard }}/8

The unit job fans out to eight concurrent jobs on one custom runner, so that runner wants a pool of eight. The lint job runs on WarpBuild-hosted capacity at $0.004 per minute and needs no pool at all, which is the usual mixed-fleet shape: hosted labels for the small jobs, BYOC labels for the jobs that must stay inside your account.

Because the workflow file is untouched, the before and after measurement is clean. Hold the workflow constant, change the pool count, and compare the Set up job duration across a week of runs on that runner type.

Managing the pool without the dashboard

Terraform support exists for BYOC on AWS, which covers BYOC runner images and custom runner sets, so a team that keeps runner definitions in version control can move the count through the same review process as any other infrastructure change. Both paths are described in the BYOC documentation.

Cost

Three documented mechanics set the bill, and only two of them land on anyone's invoice.

WarpBuild does not charge for standby disks. The WarpBuild fee stays at $0.002 per BYOC runner minute for Linux runners and $0.002 per minute for Windows runners, measured against job time. A pool of 40 disks and a pool of zero produce the same WarpBuild line item.

The initializing VM is billable for about 90 seconds. Each disk boots once so that the VM, networking, and configuration are ready, after which it is shut down. Your cloud account bills those 90 seconds at your own rate for that instance type. This is largely the boot you would have paid inside the billed job window anyway, moved ahead of the job.

The network disk stays billable while the VM is shut down. Once the VM is shut down, the network disk is still billable but the VM is not. That is the standing line item: provisioned storage that exists whether or not any job is running.

Working the numbers for a pool

Take a custom runner with a pool of 8, a 150 GB disk per runner, and 400 jobs a week landing on that runner type. Multiply by your own cloud rates, since AWS, GCP, and Azure each price instance-seconds and provisioned storage differently.

LineArithmeticResult
Initial pool fill8 disks x 90 seconds12 instance-minutes, one time
Steady-state refills400 jobs x 90 seconds600 instance-minutes per week
Standing storage8 disks x 150 GB1,200 GB provisioned continuously
WarpBuild fee for the pool0$0.00

The second row is the one people miss. Every job served from the pool consumes a disk, the control plane replaces it, and that replacement pays its own 90 seconds of initialization. Pool cost therefore tracks job count, and only the storage row tracks pool size.

Where the runner minutes themselves land

Standby disks change start time while the per-minute rate stays the same. The rates around them, checked against GitHub's published list prices on 2026-08-13:

ShapeGitHub-hosted list price per minuteWarpBuild-hosted rate per minuteWarpBuild BYOC fee per minute
Linux 2 vCPU, 8 GB$0.006 (ubuntu-latest, private repositories)$0.004$0.002
Linux 8 vCPU, 32 GB$0.022 (8-core larger runner)$0.016$0.002
Linux 16 vCPU, 64 GB$0.042 (16-core larger runner)$0.032$0.002
Windows 8 vCPU, 32 GB$0.042 (8-core larger runner)$0.032$0.002

GitHub rates come from the GitHub Actions billing reference, checked on 2026-08-13. WarpBuild rates come from the pricing page. The BYOC column is the WarpBuild fee alone; your cloud provider bills the compute, storage, and data transfer separately at your own rates.

Run the 400-job week through it. At 6 minutes of job time each, that is 2,400 runner minutes: $52.80 on the GitHub-hosted 8-core larger runner, $38.40 on warp-ubuntu-latest-x64-8x, and $4.80 in WarpBuild fees on BYOC plus whatever your cloud bills for the instances. Compare those concrete amounts with the cloud bill for your chosen instances. A standby pool cannot use spot instances, so do not apply a spot discount to this model.

A standby pool moves your cloud bill alone and leaves that structure as it is. SSO is available for a flat $250 per month, whatever the user count.

On the enterprise tier, runners pull large images and artifacts from ECR, S3, and similar stores during deployments with zero egress cost to you, whether those runners live in your cloud or ours; see zero egress on the WarpBuild enterprise tier. If you are still choosing between account placement and hosted capacity, start with WarpBuild-hosted runners compared with BYOC runners.

FAQ

What is a standby disk on a BYOC runner?

A VM of the same instance type as the runner that is booted once so that networking and the rest of the machine configuration complete, then shut down without being terminated. When GitHub requests a runner, WarpBuild powers a waiting disk back on and the job starts in about 15 seconds instead of building a machine from scratch.

How many standby disks should I configure?

The count is set per custom runner, and the documented guidance is to choose it from the number of jobs you expect to run concurrently on that runner type. A pull request workflow that fans out to eight shards on one runner type wants at least eight, otherwise the first shards start quickly and the rest wait for fresh VMs.

Do standby disks work with spot instances?

No. Spot instances are not supported for standby disks, because a spot instance can be reclaimed at any time and a waiting standby instance cannot then be guaranteed. Run standby disks on on-demand instance types and keep spot for runner types where a slower start is acceptable.

What do standby disks cost?

WarpBuild does not charge for standby disks. Your own cloud account pays for about 90 seconds of VM time while each disk initializes, and for the network disk, which stays billable while the VM is shut down. Nothing else changes on the WarpBuild invoice, which stays at $0.002 per BYOC runner minute.

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.