self-host →

//self-hosted github actions runners · your aws account

self-hosted runners, done properly.

You tuned ARC's autoscaler, fought the controller, and gave up on Windows. RunsOn is the version that just runs: ephemeral EC2 in your own AWS account, one CloudFormation stack, any instance per job.

the label is a query — pick constraints, resolved at launch

.github/workflows/ci.yml yaml
# the label is a query — each line one constraint
jobs:
  build:
    runs-on:
      - runs-on=${{ github.run_id }}
      - cpu=16
      - family=c7i
      - image=ubuntu24-full-x64
      - extras=s3-cache
    steps: [...]
cpu
family
image
extras
see all job labels →
→ resolves to c7i.4xlarge · spot · ~$0.23/hr github-hosted 16cpu: $2.52/hr ≈ 11× cheaper
7–12×

cheaper than GitHub-hosted runners — you pay AWS directly, no per-minute markup.

do the math on your bill →
1.5M+

jobs every day — ephemeral runners launched and destroyed, one box per job.

8M+

vCPUs daily — from 1 to 896 per runner, across x64 · arm64 · gpu.

running in production, every single day — ~1.5% of all github actions runs

the hard parts, handled

everything you had to bolt on yourself.

The runner is the easy 20%. The other 80% is why you're reading this page — RunsOn ships it as defaults, not as a weekend project.

01

dynamic instance selection

The instance is the job. The label is a query — family, cpu, ram, image, volume — resolved against live spot capacity at launch. No pools to size, no scale sets to babysit.

1–96cpu x64 · arm64 · gpu spot → on-demand
02

caching that's actually fast

Flip extras=s3-cache and actions/cache is backed by an S3 bucket in your account — same region, same VPC, no 10GB ceiling. Nothing else in the workflow changes.

no 10GB cap in-VPC restores
03

nested virt, both OSes

KVM for Linux, Hyper-V for Windows — nested virtualization is just a label. Android emulators, VM-based e2e suites, Windows containers: they run.

KVM Hyper-V m8i · c8i · r8i

+ docker layer caching · per-job cost reporting · spot→on-demand retry · static egress IPs · warm pools · byo AMIs

sixty seconds

same goal. a lot less to operate.

The Kubernetes cluster, the controller, the autoscaler — then the same job on ephemeral EC2 in your own account. Watch the moving parts fall away.

the reasons teams stay

“Saved around 75% of our costs, and tests now run 5× faster on gigantic spot instances.”

Tim Dumol — Founding Engineer, Expedock

“After benchmarking a lot of tools, it's the best. Costs divided by 4 — thousands of jobs per day.”

Corentin Smith — CTO, Dashdoc

“Costs down 70%, CI runtime improved up to 80%. A clear win with virtually no downside.”

Théophile D. de Segonzac — Lead DevOps, Lingoda

install

three steps. one line to migrate.

01

deploy the stack

One CloudFormation template — or the official Terraform module. VPC, cache bucket, IAM, and the scheduler come up together.

02

connect the repo

Install the GitHub App on your org. RunsOn registers ephemeral runners on demand — nothing stays running idle.

03

change one label

Swap a single line in your workflow. Every existing action, cache step, and secret keeps working untouched.

# the entire migration, in one diff
runs-on: ubuntu-latest
runs-on: runs-on=${{ github.run_id }}/runner=2cpu-linux-x64