How to Route Cheap Jobs to Cheaper Runners
Running a five-second lint check on an 8-core runner pays for cores it never uses; match the runner to the job.
Set runs-on per job so lightweight checks use the standard runner and only genuinely heavy jobs claim larger machines.
Steps
- Classify jobs as light (lint, format) or heavy (build, integration tests).
- Point light jobs at the smallest runner and heavy jobs at larger ones.
- Review quarterly; jobs grow and their right size changes.
Workflow
.github/workflows/ci.yml
jobs:
lint:
runs-on: ubuntu-latest # small, cheap
steps:
- uses: actions/checkout@v4
- run: npm run lint
integration:
runs-on: ubuntu-latest-8-cores # larger, only where it pays off
steps:
- uses: actions/checkout@v4
- run: npm run test:integrationGotchas
- Custom runner labels must be defined in org or repo runner settings first.
- Do not over-shard; each extra job pays fresh setup overhead.
- A larger runner idling on a light job is pure waste; the rate is billed per minute regardless of load.
Related guides
How to Weigh the Cost of Larger RunnersDecide when a larger GitHub Actions runner is worth it: more vCPUs finish faster but bill a higher per-minute…
How to Reduce CI Cost by Consolidating JobsCut GitHub Actions cost by merging tiny jobs, since every job pays fixed runner startup and checkout overhead…