Skip to content
6 min read·Lesson 4 of 8

Runners: GitHub-Hosted vs Self-Hosted

Compare the three runner options — GitHub-hosted, larger runners, and self-hosted — and choose the right model for cost, performance, and isolation.

Every job in GitHub Actions executes on a runner — a machine that pulls the job, runs its steps, streams logs, and reports the result. GitHub gives you three runner models with very different tradeoffs.

Option 1: GitHub-Hosted Runners

The default option specified by runs-on: ubuntu-latest / windows-latest / macos-latest. GitHub provisions a fresh VM per job, runs your steps, then destroys it.

Specifications (2026)

OSvCPURAMDiskMinute multiplier
Linux (ubuntu-latest)416 GB14 GB SSD
Windows (windows-latest)416 GB14 GB SSD
macOS (macos-latest)314 GB14 GB SSD10×

Pre-installed software

Each image comes with hundreds of pre-installed tools: every major language runtime, Docker, kubectl, gh CLI, Terraform, AWS/Azure/GCP CLIs, browsers for end-to-end testing, etc. The full lists are maintained at github.com/actions/runner-images.

When GitHub-hosted is the right choice

  • Open source projects (free, unlimited minutes for public repos)
  • Small-to-medium private teams
  • Workloads that fit comfortably in 4 vCPU / 16 GB
  • You don't want to operate runner infrastructure

Option 2: Larger Runners

For builds that need more horsepower, GitHub sells larger runners — same managed model, beefier hardware:

SizevCPURAM
4-core416 GB
8-core832 GB
16-core1664 GB
32-core32128 GB
64-core64256 GB
96-core96384 GB

ARM64 and GPU larger runners are also available. Pricing scales linearly with size. Specify them with a custom runs-on label configured in your org/repo settings.

Option 3: Self-Hosted Runners

You install the runner agent on your own machine — bare metal, VM, container, or Kubernetes pod. Jobs queued with the matching label dispatch to your runners.

# From your repo Settings → Actions → Runners → New self-hosted runner
mkdir actions-runner && cd actions-runner
curl -o actions-runner-linux-x64.tar.gz -L https://github.com/actions/runner/releases/download/...
tar xzf actions-runner-linux-x64.tar.gz
./config.sh --url https://github.com/myorg/myrepo --token AABB...
./run.sh

When self-hosted makes sense

  • Heavy compilation workloads where GitHub minutes get expensive (>$1000/month)
  • Builds requiring GPUs you already own
  • Access to internal networks (VPN, private package registries)
  • Specialised hardware (FPGAs, dedicated databases)
  • Compliance requirements that prohibit cloud-managed runners

Self-hosted security warning

The runner agent runs whatever code your workflows tell it to run. If you attach a self-hosted runner to a public repo, any contributor can submit a PR that runs arbitrary code on your infrastructure. GitHub explicitly recommends against this. For public repos, use only GitHub-hosted runners.

Ephemeral vs persistent

The recommended pattern for self-hosted is ephemeral runners — each runner accepts one job, then exits. This eliminates job-to-job state leakage. Implementations:

  • actions-runner-controller (ARC): Kubernetes operator that spins up runner pods on demand
  • Auto-scaling EC2/Azure VM: CloudFormation/Terraform templates
  • Plain Docker: spawn a container per job

Runner Groups

For organizations and enterprises, runners can be grouped (e.g., "production-runners", "ml-gpu-runners") with access policies controlling which repos/workflows can dispatch jobs to them. This is how mature organisations safely share runner fleets.

Container Jobs

An orthogonal concern: regardless of where your runner lives, you can ask a job to execute inside a Docker container on that runner:

jobs:
  test:
    runs-on: ubuntu-latest
    container:
      image: node:20-alpine
    steps:
      - uses: actions/checkout@v4
      - run: npm ci && npm test

This gives you reproducible environments without managing a specialised runner image.

Choosing a Model

WorkloadBest runner
OSS project, GitHub Actions tutorialGitHub-hosted (free for public)
Startup with 10 engineersGitHub-hosted, occasionally larger
Heavy nightly builds, predictable spend > $1500/moSelf-hosted ephemeral (ARC on Kubernetes)
Mac builds for iOSGitHub-hosted macOS (specialised hardware otherwise painful)
Build inside corporate VPNSelf-hosted inside the VPN
GPU training a few times per weekLarger runners with GPUs

Most teams start GitHub-hosted, monitor minute consumption, and migrate hot workloads to self-hosted only when economics dictate. Premature self-hosting is a common operational mistake.

Key Takeaways

  • GitHub-hosted runners are clean VMs created and destroyed per job — perfect for most public workloads.
  • Larger runners (4-vcpu through 96-vcpu, GPU, ARM) are billed by the minute at higher rates.
  • Self-hosted runners run in your infrastructure — cheaper for heavy workloads but you operate them.
  • Never use self-hosted runners with public repos unless you understand the security implications.
  • Runner groups (Enterprise) let you partition self-hosted runners across teams and workflows.

Test your knowledge

Try exam-style practice questions to reinforce what you've learned.

Practice Questions →