How Do I Choose a GitHub Actions Runner Size?
Size a GitHub Actions runner from measured utilization: start most builds on 4 vCPU, move up a label when sustained CPU or memory reaches 80 percent.
Last verified:
Choose a GitHub Actions runner size by measuring what your jobs actually use, then picking the smallest label that keeps CPU, memory, filesystem, and disk I/O under 80 percent for the length of the job. Before any measurement exists, start lint and type-check jobs on 2 vCPU, most builds and test suites on 4 vCPU, and reserve 16 vCPU and above for monorepo compiles and wide integration matrices.
Answer
Runner size is a cost decision and a wall-clock decision at the same time. Each step up the ladder doubles the per-minute rate, so a larger runner returns money only when it cuts the job duration by more than half, and a smaller runner saves money only when the extra minutes stay cheap enough to be worth the wait.
Here is the default starting point per workload shape, with the catalog label and rate on each platform. The three columns below cover the platforms where a size choice exists at every tier.
| Workload shape | Linux x64 | Linux ARM64 | Windows |
|---|---|---|---|
| Lint, formatting, type checks, short unit suites | warp-ubuntu-latest-x64-2x, 2 vCPU, 8 GB, $0.004/min | warp-ubuntu-latest-arm64-2x, 2 vCPU, 8 GB, $0.003/min | warp-windows-latest-x64-4x, 4 vCPU, 16 GB, $0.016/min |
| Application test suites, interpreted-language builds, packaging | warp-ubuntu-latest-x64-4x, 4 vCPU, 16 GB, $0.008/min | warp-ubuntu-latest-arm64-4x, 4 vCPU, 16 GB, $0.006/min | warp-windows-latest-x64-4x, 4 vCPU, 16 GB, $0.016/min |
| Compiled builds, Docker image builds, parallel test shards | warp-ubuntu-latest-x64-8x, 8 vCPU, 32 GB, $0.016/min | warp-ubuntu-latest-arm64-8x, 8 vCPU, 32 GB, $0.012/min | warp-windows-latest-x64-8x, 8 vCPU, 32 GB, $0.032/min |
| Monorepo builds, Rust and C++ compiles, large Gradle or Bazel graphs | warp-ubuntu-latest-x64-16x, 16 vCPU, 64 GB, $0.032/min | warp-ubuntu-latest-arm64-16x, 16 vCPU, 64 GB, $0.024/min | warp-windows-latest-x64-16x, 16 vCPU, 64 GB, $0.064/min |
| Whole-repo rebuilds, heavy link steps, wide integration matrices | warp-ubuntu-latest-x64-32x, 32 vCPU, 128 GB, $0.064/min | warp-ubuntu-latest-arm64-32x, 32 vCPU, 128 GB, $0.048/min | warp-windows-latest-x64-32x, 32 vCPU, 128 GB, $0.128/min |
Shapes, storage, and rates come from the cloud runners documentation and the WarpBuild pricing page. Linux runners carry a 150GB SSD at every size and Windows runners carry a 256GB SSD. Windows has no 2 vCPU tier: it was removed on June 8, 2026, so 4 vCPU at $0.016 per minute is the Windows floor and the first two rows collapse onto the same label.
macOS sizing works differently because the catalog offers two shapes rather than a ladder: 6 vCPU with 22 GB at $0.08 per minute and 12 vCPU with 44 GB at $0.16 per minute. Pick the larger one when Xcode builds run out of memory or when simulator matrices run in parallel inside a single job.
Treat these rows as a starting label and nothing more. The measured numbers decide the final size, and the next section covers where those numbers live.
Detail
Measure first, then move one label
Every WarpBuild runner reports utilization to the observability view, grouped by repository, workflow, job, and instance type. The Recommendations view applies fixed thresholds and highlights the jobs that cross them, leaving the label change to you.
| Metric | Threshold that marks an undersized instance |
|---|---|
| Max sustained CPU | 80 percent or higher |
| Max memory utilization | 80 percent or higher |
| Max filesystem utilization | 80 percent or higher |
| Max disk I/O | 80 percent or higher of supported throughput |
Low utilization is the opposite signal. A job that holds CPU in the low tens and memory under 20 percent on every run is paying for cores it never touches, and the Recommendations view flags it as over-provisioned.
Two details change how you read the numbers. Observability collects metrics and logs only for jobs longer than about one minute, so a fleet of 30 second jobs shows gaps. And a single hot run proves little: read the value that holds across a week of runs, since a p90 duration far above p75 with CPU pinned at 80 percent is the usual signature of an instance that copes most of the time and falls over when the machine is busy.
Each metric points at a different fix. Sustained CPU at the threshold means more vCPU. Memory at the threshold means the next size up, since memory and vCPU scale together in this catalog. Filesystem near 80 percent on a 150GB SSD usually means artifacts left behind inside the job rather than an undersized machine. High disk I/O with idle cores usually means a caching problem, and the guide to finding the slow step walks through separating those cases.
Sizing is the cheapest lever of the set, so pull it before reaching for the others.
What a size step costs against GitHub-hosted list prices
Rate doubles per step within a platform, which makes the trade explicit. Here is the ladder next to the nearest GitHub-hosted shape.
| WarpBuild label | Shape | WarpBuild rate | Nearest GitHub-hosted runner | GitHub rate | Difference |
|---|---|---|---|---|---|
warp-ubuntu-latest-x64-2x | 2 vCPU, 8 GB | $0.004/min | ubuntu-latest, private repositories | $0.006/min | 33 percent lower list price |
warp-ubuntu-latest-x64-4x | 4 vCPU, 16 GB | $0.008/min | 4-core Linux larger runner | $0.012/min | 33 percent lower list price |
warp-ubuntu-latest-x64-8x | 8 vCPU, 32 GB | $0.016/min | 8-core Linux larger runner | $0.022/min | 27 percent lower list price |
warp-ubuntu-latest-x64-16x | 16 vCPU, 64 GB | $0.032/min | 16-core Linux larger runner | $0.042/min | 24 percent lower list price |
warp-ubuntu-latest-x64-32x | 32 vCPU, 128 GB | $0.064/min | 32-core Linux larger runner | $0.082/min | 22 percent lower list price |
warp-ubuntu-latest-arm64-2x | 2 vCPU, 8 GB | $0.003/min | ubuntu-24.04-arm, private repositories | $0.005/min | 40 percent lower list price |
warp-ubuntu-latest-arm64-4x | 4 vCPU, 16 GB | $0.006/min | 4-core Linux ARM64 larger runner | $0.008/min | 25 percent lower list price |
warp-ubuntu-latest-arm64-8x | 8 vCPU, 32 GB | $0.012/min | 8-core Linux ARM64 larger runner | $0.014/min | 14 percent lower list price |
warp-ubuntu-latest-arm64-16x | 16 vCPU, 64 GB | $0.024/min | 16-core Linux ARM64 larger runner | $0.026/min | 8 percent lower list price |
warp-ubuntu-latest-arm64-32x | 32 vCPU, 128 GB | $0.048/min | 32-core Linux ARM64 larger runner | $0.05/min | 4 percent lower list price |
warp-windows-latest-x64-4x | 4 vCPU, 16 GB | $0.016/min | 4-core Windows larger runner | $0.022/min | 27 percent lower list price |
warp-windows-latest-x64-8x | 8 vCPU, 32 GB | $0.032/min | 8-core Windows larger runner | $0.042/min | 24 percent lower list price |
warp-windows-latest-x64-16x | 16 vCPU, 64 GB | $0.064/min | 16-core Windows larger runner | $0.082/min | 22 percent lower list price |
warp-windows-latest-x64-32x | 32 vCPU, 128 GB | $0.128/min | 32-core Windows larger runner | $0.162/min | 21 percent lower list price |
GitHub list prices checked on 2026-08-13 against the GitHub Actions per-minute rate list. GitHub gives public repositories a 4 vCPU, 16 GB Linux shape at no charge, so every GitHub number above is the private-repository price that paying teams see on an invoice.
The ARM64 column is where sizing and platform choice meet. A 4 vCPU ARM64 runner at $0.006 per minute is the same shape as the 4 vCPU x64 runner at $0.008, so a job with no x86 dependency lowers its rate without giving up a core. ARM64 runners do not support nested virtualization, which keeps Android emulator jobs on x64.
The break-even test before you move up
One arithmetic rule settles most upgrade arguments. Rate doubles per step, so the bill stays flat only when duration falls below half. Anything above that is buying wall-clock time, which is often the right purchase, and it should be a deliberate one.
Take a job that runs 800 times a month with a p90 duration of 10.0 minutes on warp-ubuntu-latest-x64-4x. That is 8,000 minutes at $0.008, or $64.00 a month. The break-even duration on warp-ubuntu-latest-x64-8x at $0.016 is 5.0 minutes. Assume the dominant step parallelizes and p90 lands at 7.0 minutes: 5,600 minutes at $0.016 is $89.60, which is $25.60 more per month and returns 3 minutes on every run, or 2,400 minutes a month of engineers waiting on a pull request.
The downsize case runs the same way. A lint job runs 1,200 times a month at 4.0 minutes p90 on warp-ubuntu-latest-x64-8x with max sustained CPU at 22 percent. That is 4,800 minutes at $0.016, or $76.80. Assume 2 vCPU stretches it to 6.5 minutes: 7,800 minutes at $0.004 is $31.20, a reduction of $45.60 a month. The intermediate stop at 4 vCPU, assuming 5.0 minutes, costs 6,000 minutes at $0.008, or $48.00. Run the numbers at both stops before committing, because the middle rung often wins.
Sizing one workflow job by job
Sizing is a per-job decision, so a single workflow usually carries several labels.
name: ci
on:
pull_request:
branches: [main]
jobs:
lint:
runs-on: warp-ubuntu-latest-x64-2x
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 22
cache: npm
- run: npm ci
- run: npm run lint
unit-tests:
runs-on: warp-ubuntu-latest-x64-4x
strategy:
matrix:
shard: [1, 2, 3, 4]
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 22
cache: npm
- run: npm ci
- run: npm test -- --shard=${{ matrix.shard }}/4
build-image:
runs-on: warp-ubuntu-latest-arm64-8x
steps:
- uses: actions/checkout@v4
- run: docker build -t app:${{ github.sha }} .
integration:
runs-on: warp-ubuntu-latest-x64-16x
steps:
- uses: actions/checkout@v4
- run: ./scripts/integration.shAssume the lint job takes 3 minutes, each test shard takes 5 minutes, the image build takes 6 minutes, and the integration job takes 14 minutes.
| Job | Runner | Billed minutes | Rate | Cost per run |
|---|---|---|---|---|
| lint | warp-ubuntu-latest-x64-2x | 3 | $0.004/min | $0.012 |
| unit-tests (4 shards) | warp-ubuntu-latest-x64-4x | 20 | $0.008/min | $0.160 |
| build-image | warp-ubuntu-latest-arm64-8x | 6 | $0.012/min | $0.072 |
| integration | warp-ubuntu-latest-x64-16x | 14 | $0.032/min | $0.448 |
| Total | 43 | $0.692 |
At 400 pull request runs a month that workflow costs $276.80. The same minutes on the nearest GitHub-hosted shapes come to $0.018, $0.240, $0.084, and $0.588, which is $0.930 per run and $372.00 a month, a difference of $95.20 on list prices checked on 2026-08-13 at docs.github.com.
Two lines in that table deserve a second look. The integration job holds 65 percent of the cost, so it is the first candidate for measurement, and if its utilization sits in the low tens then 8 vCPU at the same duration takes $0.224 off every run. The shard count is a separate lever from the size: four shards of 5 minutes bill 20 minutes and return a result in 5, while one unsharded job at 18 minutes bills 18 and returns a result in 18.
Where a bigger size stops helping
Some jobs ignore vCPU entirely. A job dominated by network waits, an artifact upload, a rate-limited API, or a single-threaded compiler step runs for the same wall-clock minutes on 32 vCPU as on 4, and the invoice doubles at every step. The larger runners cost guide works through the sizes where that trade turns.
Queue time is another number that size will not move. When jobs sit waiting rather than running, the fix is concurrency and label routing, and the duration you are trying to shrink lives outside the machine.
Cold caches look like an undersized runner in exactly the same way: high disk I/O, moderate CPU, and a long tail on p90. Confirm the cache is warm before you move a label, because a bigger machine downloads the same dependencies at the same rate. The observability solution page covers reading those metrics per job, and the Linux x64 runner page lists every image and size available at each rate.
Related Questions
When does a bigger GitHub Actions runner not pay for itself?
Each size step doubles the per-minute rate, so an upgrade holds the bill flat only when the job finishes in under half the time. Jobs that wait on network calls, run one long single-threaded step, or queue behind a rate-limited service keep the same duration on more cores and double the cost. Measure the p90 duration at both sizes over a week before deciding, and treat any upgrade above the break-even point as a purchase of wall-clock time.
How do I know my GitHub Actions runner is too small?
The Recommendations view highlights a job as under-provisioned when max sustained CPU, max memory utilization, or max filesystem utilization reaches 80 percent, or when max disk I/O reaches 80 percent of supported throughput. Utilization in the low tens on every run points the other way, toward a smaller label. The thresholds and the collection details are in the observability documentation.
Is a 2 vCPU runner enough for GitHub Actions?
For lint, formatting, type checks, and short unit suites, yes. warp-ubuntu-latest-x64-2x carries 2 vCPU, 8 GB, and a 150GB SSD at $0.004 per minute. Move up when sustained CPU sits at 80 percent for most of the job or a process gets killed for memory. Windows starts at 4 vCPU because the 2 vCPU Windows tier was removed on June 8, 2026.
Should I pick ARM64 at the same size to lower the rate?
ARM64 is the cheaper Linux platform at every size. warp-ubuntu-latest-arm64-4x costs $0.006 per minute against $0.008 for the x64 runner of the same 4 vCPU, 16 GB shape. Move jobs that carry no x86 dependency and no nested virtualization requirement, and check the full rate list on the WarpBuild pricing page before you plan the switch.
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.