Choosing Between GitHub-Hosted and Self-Hosted Runners for Actions
Decide whether to use GitHub-hosted or self-hosted runners based on security, cost, and infrastructure needs.
11 Feb 2026, 10:37 UTC

Decision Overview
Choose whether to run GitHub Actions workflows on GitHub-hosted runners or on self-hosted runners you manage.
Constraints
- Security exposure of the runner environment
- Predictable cost for high-volume workloads
- Need for specialized hardware (GPU, large memory) or access to private networks
- Maintenance overhead you are willing to accept
Comparison Table
| Aspect | GitHub-hosted runner | Self-hosted runner |
|---|---|---|
| Management | Fully managed by GitHub; automatic OS updates | User-managed; requires patching, scaling, monitoring |
| Isolation | Each job gets a fresh VM; strong isolation | Reuses the same host; isolation depends on container/runtime setup |
| Cost model | Per-minute billing (free minutes vary by plan) | No per-minute charge from GitHub; you pay for the host infrastructure |
| Hardware flexibility | Fixed CPU, RAM, disk limits per runner type | Customizable (GPU, SSD, high-memory, ARM, etc.) |
| Network access | Runs in GitHub’s public cloud; no direct access to private resources unless using VPN or proxy | Can be placed inside your VPC or data-center; direct access to internal services |
Trade-offs
If you prioritize zero maintenance and strong job-to-job isolation, GitHub-hosted runners are the simpler choice. They are ideal for public repositories or workloads that fit within the default resource limits.
When you need specialized hardware, want to keep build artifacts on-premises, or must avoid per-minute charges for a large number of workflow runs, a self-hosted runner reduces cost and gives you full control. The trade-off is the operational burden: you must keep the OS updated, monitor the runner agent, and ensure that public repository workflows are not allowed to execute on the same hosts, otherwise malicious code could gain remote access.
Implementation Example
The following workflow snippet shows how to select the runner type at the job level.
name: Example CI
on:
push:
branches: [ main ]
jobs:
build:
runs-on: ubuntu-latest # GitHub-hosted runner
steps:
- uses: actions/checkout@v4
- run: echo \"Running on a hosted VM\"
deploy:
runs-on: self-hosted # Self-hosted runner label
steps:
- uses: actions/checkout@v4
- run: ./deploy.sh # assumes deploy.sh exists in repo
Verifying a GitHub-hosted runner
- Push the workflow to the repository.
- Go to the
Actionstab, select the latest workflow run. - In the job log, look for the line
Runner: Ubuntu(or similar) confirming the hosted VM.
Verifying a self-hosted runner
- Ensure a self-hosted runner is registered at the repository or organization level (
Settings → Actions → Runners) and shows statusIdleorActive. - Add a label to the runner (e.g.,
self-hosted,gpu) during registration. - Push a workflow that uses
runs-on: self-hosted(or a specific label). - After the run starts, check the job log for a line containing the runner name you registered, confirming the job executed on your host.
Limitations and Practical Checks
- GitHub-hosted runners have fixed disk space (≈14 GB) and may throttle if you exceed it; verify by checking the
Runnerlog forDisk spacewarnings. - Self-hosted runners require network outbound access to GitHub’s API endpoints (
https://github.comandhttps://api.github.com) and inbound access if you use webhook-based triggers; test connectivity withcurl -I https://github.comfrom the host. - To confirm cost savings, compare the monthly bill for the host instance (e.g., EC2 t3.medium) against the projected per-minute charges for the same number of workflow minutes on GitHub-hosted runners.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.