[INDEX] // ALL_DOCS ›
[TOC] // ON_THIS_PAGE ›
This page is the canonical reference for every selector you can pass to runs-on: with machine.dev. For pricing see Pricing; for which workload fits which runner see CPU vs GPU.
Label format
machine.dev reads everything it needs from the label in runs-on:. Pack every selector into a single label string, led by machine and separated by /:
runs-on: machine/gpu=l4/tenancy=spot
Rules:
- Always lead with
machine. GitHub only routes a job to machine.dev when the label carries themachinesentinel, so every packed label starts with it. - Separate selectors with
/. Eachkey=valuesegment is one selector.machine/cpu=16/tenancy=spot/regions=us-east-1requests a 16-vCPU spot runner pinned tous-east-1. - Multi-value
regionsputs the commas inside the value:machine/gpu=l4/regions=us-east-1,us-east-2.
Pin one runner to one job with id=
Add id=${{ github.run_id }} to tie the runner to a specific workflow run. machine.dev registers the runner with GitHub using the exact label the job requested — including the unique id — so the runner matches only that job:
runs-on: machine/id=${{ github.run_id }}/gpu=l4/tenancy=spot
This is the recommended form when many jobs run at once. Without a unique value in the label, GitHub can hand a queued job to any idle runner whose labels are a superset of the job’s request — so a runner provisioned for one job can be “stolen” by another job with an overlapping label set. A unique id removes that overlap, so one runner serves exactly one job. For matrix jobs, make it per-job-unique, e.g. id=${{ github.run_id }}-${{ matrix.gpu }}.
Migrating from runs-on.com
The packed label is a drop-in match for runs-on.com-style syntax, and machine.dev also accepts runs-on’s spellings inside it so you can keep one-line configs you copy across. They translate to the native selectors below:
| runs-on.com spelling | machine.dev selector |
|---|---|
spot=true | tenancy=spot |
spot=false | tenancy=on_demand |
disk=<gb> / volume=<gb> | disk_size=<gb> |
region=<r> | regions=<r> |
The native keys (gpu, cpu, ram, architecture, tenancy, regions, disk_size, disk_iops, disk_throughput, metrics, metrics_interval, id, runner) pass through unchanged.
Legacy list form. The older array syntax —
runs-on: [machine, gpu=l4, tenancy=spot]— is still accepted, so existing workflows keep working untouched. It’s no longer the recommended style: the packed form above is the drop-in match for runs-on.com syntax and makes it ergonomic to thread the per-jobid=${{ github.run_id }}correlation that prevents job-stealing. Prefer the packed form for new workflows.
Required selector
| Selector | Description |
|---|---|
machine | Required, always the leading segment. Tells GitHub Actions to route the job to a machine.dev runner. |
Runner type (pick one)
| Label | Description |
|---|---|
cpu=N | CPU runner. N is one of: 2, 4, 8, 16, 32, 48, 64 |
gpu=TYPE | GPU runner. TYPE is one of: t4g, t4, l4, a10g, l40s, trainium, inferentia2 |
Optional labels
| Label | Default | Description |
|---|---|---|
architecture | x64 | x64 or arm64. CPU runners support both. T4G is always ARM64. |
cpu | 4 | With gpu= only. Scales vCPU: 4, 8, or 16. |
ram | varies | With gpu= only. See GPU Runners. |
tenancy | on_demand | on_demand or spot. Spot is 70–90% cheaper. |
regions | auto | Comma-separated AWS region codes. Auto picks cheapest. |
disk_size | 100 | Root volume in GB. Range: 1–16,384. |
disk_iops | 6000 | Provisioned IOPS. Range: 6,000–16,000. |
disk_throughput | 250 | Throughput in MB/s. Range: 250–1,000. |
metrics | true | true or false. Enables instance metrics. |
metrics_interval | 60 | Collection interval in seconds. Range: 1–60. |
Storage: Every runner uses a gp3 EBS root volume. The default 6,000 IOPS and 250 MB/s throughput are included at no charge. Increasing above the defaults incurs prorated EBS charges — see Pricing.
Metrics: machine.dev collects metrics by default for every job and renders them as sparkline charts on the dashboard. Collected: CPU, memory, disk I/O, network, plus GPU utilization/memory/temperature/power on GPU runners.
There are no environment variables. machine.dev reads your requirements from the labels in
runs-on:. Your job’s environment is determined by the runner image, not by machine.dev — use the labels themselves as your source of truth (gpu=l4, etc.).
Available regions
| Region code | Location |
|---|---|
us-east-1 | US East (N. Virginia) |
us-east-2 | US East (Ohio) |
us-west-2 | US West (Oregon) |
ca-central-1 | Canada (Central) |
eu-south-2 | Europe (Spain) |
ap-southeast-2 | Asia Pacific (Sydney) |
See Regions & availability for which GPU types are available in which regions and how auto-selection works.
Examples
Minimal CPU job
jobs:
build:
runs-on: machine/cpu=8
steps:
- uses: actions/checkout@v4
- run: make
Minimal GPU job
jobs:
train:
runs-on: machine/gpu=t4g # 4 vCPU, 8 GB RAM, 16 GB VRAM, ARM64
steps:
- uses: actions/checkout@v4
- run: nvidia-smi
Spot CPU build with multiple regions
runs-on: machine/cpu=32/tenancy=spot/regions=us-east-1,us-east-2,eu-south-2
Full-control GPU fine-tune with custom storage and metrics
runs-on: machine/id=${{ github.run_id }}/gpu=l40s/cpu=16/ram=128/tenancy=spot/regions=us-east-1/disk_size=500/disk_iops=10000/metrics_interval=10
# id=<run_id> → pins this runner to this job (no stealing)
# disk_size=500 → bigger volume for model checkpoints
# disk_iops=10000 → higher IOPS for fast checkpoint writes
# metrics_interval=10 → finer-grained metrics
ARM64 CPU build
runs-on: machine/cpu=16/architecture=arm64
Next steps
- GPU Runners — every GPU type and configuration
- CPU Runners — every CPU configuration
- Regions — region availability and auto-selection
- Pricing — full per-minute rates