Skip to content
Latchkey LogoLatchkey home

GitHub-hosted vs self-hosted vs managed runners

The github hosted vs self hosted runners question has a third answer that did not exist when the question was first asked, and for most teams it is the right one: managed runners. Stay GitHub-hosted while your minutes fit the included allowance or your repositories are public, go self-hosted when you need hardware, network position or persistent state that nobody rents, and take managed runners for everything in between, which is most CI.

Three runner models: $0.006 a minute GitHub-hosted, $0.0025 managed, no GitHub charge self-hosted
The same job under three models, with the published rates read 20 September 2026. The self-hosted column has no per-minute rate because GitHub charges nothing for it.

Every GitHub Actions job runs on a runner, and there are exactly three places that runner can come from: GitHub, you, or a vendor who operates it for you. That choice is the largest single lever on what CI costs and how much of your week it takes.

They are not a ladder you climb but three trades: GitHub-hosted trades money for zero setup, self-hosted trades your time for control, and managed runners trade a vendor relationship for most of the self-hosted economics without the pager. Plenty of mature teams run all three at once, because runner selection is per job.

Every rate and limit below was read from docs.github.com or the named vendor's own page on 20 September 2026. The self-hosted column has no published per-minute rate, and says so rather than carrying a made-up figure.

The three models, on the same rows (read 20 September 2026)

GitHub-hostedSelf-hostedManaged (Latchkey shown)
Price per minute, 2 vCPU Linux x64$0.006 on a private repo (2 vCPU, 8 GB RAM, 14 GB SSD); free and unlimited on public reposNot published, because GitHub does not charge for it: its billing page states Actions usage is free for self-hosted runners. You pay your cloud bill, including the idle minutes between jobs$0.0025 (2 vCPU, 8 GB RAM, 100 GB disk)
Price per minute, 4 vCPU Linux x64$0.012 as a larger runner; the free public-repo standard runner is already 4 vCPU and 16 GBYour instance rate. A 4 vCPU cloud VM is cheap per hour and expensive per idle hour, which is the whole economic argument$0.005 (4 vCPU, 16 GB RAM, 100 GB disk)
Free tier2,000 minutes a month on Free, 3,000 on Team, 50,000 on Enterprise Cloud, private repos only; larger runners are always billedUnlimited from GitHub. Your cloud provider has opinions30-day trial, then 2,000 included minutes a month on Developer, 4,000 on Launch, 6,000 on Scale
Billing granularityEvery job is rounded up to the nearest whole minuteYour cloud provider's, which is usually per second with a minimum, applied to instance uptime rather than job timePer minute
Runner sizes and OSLinux x64 and arm64, Windows x64 and arm64, macOS on M-series and Intel; larger runners to 96 vCPU x64 and 64 vCPU arm64Anything you can boot and install the runner agent on, including hardware nobody rents: GPUs, bare metal, an on-premises box next to the license dongleVaries by vendor. Latchkey is 2 to 16 vCPU on Ubuntu 24.04 x86_64 only; Blacksmith and Depot add arm64, Windows and macOS
Cache: type, limit, persistenceactions/cache, 10 GB per repository, entries removed after 7 days without access, restorable only from the same or the default branchactions/cache still goes to GitHub and keeps the same 10 GB limit, unless you run your own cache server. What you do get free is a warm local disk between jobsVendor-provided and usually larger: Latchkey publishes no size and keeps entries 14 days, 25 GB per repo per week on Blacksmith, metered storage on Depot and Namespace
Docker build accelerationNone built in. cache-to: type=gha writes into the same 10 GB storeWhatever you build. A persistent BuildKit cache on a long-lived host is the single best reason to self-host, and it is also the thing that fills the diskVendor actions with a managed layer cache: latchkey-dev/docker-cache-action@v1, or Blacksmith's builder on a sticky disk
Concurrency limits20 concurrent jobs on Free, 40 on Pro, 60 on Team, 500 on Enterprise Cloud. macOS is capped separately at 5, or 50 on EnterpriseYour fleet size, and your autoscaler's reaction time. Unlimited in theory, queued in practiceNot published by most vendors; Blacksmith states it imposes none. Latchkey warm-pool capacity varies by plan
Where jobs runGitHub's own hosted fleetYour infrastructure, your VPC, your network position. This is the reason most regulated teams are hereThe vendor's cloud, or your own account on the vendors that offer a bring-your-own-cloud mode
Self-healing or retriesNone. A failed job waits for a person, or for retry logic you wrote yourselfNone, and the runner host is now also yours to fix when it wedges, fills up or goes offline mid-jobLatchkey diagnoses and retries transient failures inside the run; most managed vendors do not offer this
Setup change requiredNone; this is the defaultRunner agents, an autoscaler, images, patching, secrets rotation, disk cleanup, plus a runs-on labelA runs-on label change, and for some vendors a GitHub App install

GitHub-hosted: the default, and why it stops being free

The standard runner is the whole story. On a private repository it is 2 vCPU, 8 GB of RAM and 14 GB of SSD; on a public repository the same ubuntu-latest label gives 4 vCPU and 16 GB, free and unlimited. That asymmetry is why a workflow gets slower the week a repository is made private.

The bill arrives from two directions. Minutes are rounded up per job, so a matrix of forty 70-second jobs bills as 80 minutes rather than 46.7. And included minutes are consumed at the runner multiplier, where macOS is 10x, so a Team plan's 3,000 included minutes are gone after 300 macOS minutes.

The ceilings are the other half: 14 GB of disk is why no space left on device is so common, and 8 GB of RAM is why exit code 137 turns up on builds that were fine last quarter.

Self-hosted: cheap compute, expensive attention

GitHub charges nothing for self-hosted Actions usage; its billing page says so in as many words. What you pay instead is your cloud bill plus the part nobody costs in advance: the autoscaler that has to be right, the images that drift, the disk that fills because a persistent BuildKit cache is why you self-hosted, and the runner that goes offline halfway through a release.

The economics only work at high utilisation. A fleet sized for your worst hour is mostly idle for the other twenty-three, and idle bills. Ephemeral autoscaled runners fix that and reintroduce the cold start you were avoiding, in exchange for the strongest security posture of the three models, because nothing survives between jobs.

None of this argues against self-hosting. It argues for being honest about why. There are four good reasons: hardware nobody rents, a network position you need, a compliance answer that requires jobs inside your own account, and volume large enough that a flat cloud commitment beats any metered rate. "It is cheaper" is not one of them on its own, because it is only cheaper once you refuse to count your own time.

Managed runners: the model that did not exist for the original question

A managed runner vendor operates the fleet and sells you the minutes. To the workflow it is indistinguishable from GitHub-hosted: same actions, same secrets, same matrix, one different label. To the invoice it is closer to self-hosted, because you pay compute rates rather than platform rates.

The category is crowded enough to have shape. Blacksmith and Depot sell runners on their own hardware with arm64, Windows and macOS. Namespace sells shapes and cache volumes on a prepaid plan. RunsOn and the bring-your-own-cloud modes run the fleet inside your AWS account, a hybrid of this model and the last. Latchkey sells Linux x64 only and adds what none of the others do: diagnosing a transient failure and retrying it inside the run.

The honest cost of this model is vendor risk, and it is not theoretical: BuildJet shut down in March 2026 and Cirrus CI followed in June. The mitigation is the thing that makes adoption cheap. Because it is a label, leaving is a label.

Cost: the same month under all three models

Ten thousand Linux minutes at 2 vCPU plus two thousand macOS minutes a month, on a private repository. The self-hosted row is the only one where the published price is not the price.

Linux computemacOS computeWhat else you payMonthly total
GitHub-hosted$60 at $0.006/min$124 at $0.062/minNothing$184
Self-hostedYour instance rate for the hours the fleet is up, not the minutes jobs runApple hardware or a licensed Mac cloud; the most expensive thing to self-hostAutoscaler, images, patching, disk cleanup, and the pagerNot publishable: it is your cloud bill plus your time
Managed (Latchkey)$25 at $0.0025/minNot offered: $124 on GitHub-hosted$5 to $49 a month for the plan, plus seats past the plan's own at $5$149 plus the plan

The row that will not resolve to a number is the point of the table, not a gap in it. Self-hosted cost is dominated by utilisation and by engineering hours, and both of those are yours. Measure it rather than guess: the hours your fleet was up last month times your instance rate, plus the hours your team spent on it. Teams that do this honestly find the compute was the small half. Two things make self-hosting look better than that sounds: GitHub charges nothing for the Actions usage itself, and a warm disk with a persistent build cache is worth real minutes on a Docker-heavy pipeline. The managed row is gross too: its plan fee is separate from the compute, and its 2,000 to 6,000 included minutes are not netted off.

Speed

Not benchmarked yet; the runner benchmark report will replace this section. There is no honest ranking without running the same workload on all three, and the number everyone quotes is a vendor multiple measured on a workload the vendor chose.

What the published specifications do say: a standard private-repo GitHub-hosted runner is the smallest machine of the three at 2 vCPU and 8 GB, a self-hosted runner is as fast as whatever you buy and starts warm if it is long-lived, and managed vendors sell larger sizes at lower rates than GitHub's larger runners.

Reliability

Each model fails differently, and that is more useful than any uptime number. GitHub-hosted fails as an opaque platform incident you wait out. Self-hosted fails as your infrastructure: a full disk, a wedged agent, a runner that lost communication mid-job and took the run with it. Managed runners fail as a vendor incident, plus the risk the vendor leaves the market.

All three behave the same on a bad job: a registry timeout or an out-of-memory kill bills, and the re-run bills again. Self-hosting makes this worse rather than better, because host state joins your failure surface. To size that line item before you pick a model, count the runs in your Actions history that passed on a second attempt with no code change in between.

When to choose each

  • GitHub-hosted when your repositories are public, when your minutes fit the included allowance, when your bill is mostly macOS (it is the cheapest macOS of the three), or when adding a vendor would mean redoing a compliance answer.
  • Self-hosted when you need hardware nobody rents, a network position inside your own VPC, jobs inside your own account for compliance, or a persistent build cache on a long-lived host. Budget the fleet as infrastructure, because that is what it is.
  • Managed when the answer to "why are we self-hosting" is only ever cost, when your Linux bill has outgrown the included allowance, or when you want larger machines without operating them. Check the vendor's OS coverage first: Latchkey is Linux x64 only, so a macOS or Windows job stays where it is.

Switching: the exact diff

Moving between GitHub-hosted and managed is one line per job. Moving to self-hosted is one line per job plus a fleet, which is the asymmetry the table cannot show.

.github/workflows/ci.yml
 jobs:
   test:
-    runs-on: ubuntu-latest
+    runs-on: latchkey-medium      # managed: label only

   gpu-eval:
-    runs-on: ubuntu-latest
+    runs-on: [self-hosted, linux, gpu]   # plus an agent, an image and an autoscaler

   ios:
     runs-on: macos-latest        # left alone: cheapest macOS of the three

The verdict

Stay on GitHub-hosted if your repositories are public or your minutes fit the allowance, because nothing paid competes with free and the default costs you no decision. Self-host when you have a reason that is not cost, which means hardware, network position, compliance or a persistent cache, and budget it as infrastructure with a person attached rather than as a saving. For everyone else, and that is most teams, managed runners are the model the original question did not have: self-hosted economics, no fleet, and a runs-on line you can revert in a minute if it disappoints. The caveats are real and worth saying out loud. Managed vendors leave the market, most of them cover only some operating systems, and none of the three models, on its own, does anything about the job that failed at 2am for a reason that had nothing to do with your code.

Frequently asked questions

When should you use self-hosted runners vs GitHub-hosted runners?
Self-host when you need something GitHub does not rent: GPUs or other specific hardware, a network position inside your own VPC, jobs in your own account for compliance, or a persistent build cache on a long-lived host. Stay GitHub-hosted when your repositories are public, your minutes fit the allowance, or your bill is mostly macOS. Choosing self-hosted purely to save money usually means the ops time has not been counted.
Per minute charges for self hosted runners?
GitHub's billing page states that Actions usage is free for self-hosted runners, as read on 20 September 2026. What you pay is your cloud provider's instance rate for the whole time the fleet is up, not just the minutes jobs run, which is why utilisation rather than rate decides whether self-hosting is cheaper.
Which GitHub Actions services let you run jobs on faster hardware without self-hosting?
Managed runner vendors: Blacksmith, Depot, Namespace, WarpBuild, Ubicloud, RunsOn and Latchkey, plus GitHub's own larger runners, which go to 96 vCPU on x64. All of them are adopted with a runs-on label change, and the vendors are typically cheaper per minute than GitHub's larger runners at the same size.
What hardware do GitHub-hosted runners actually give you?
On a private repository the standard Linux runner is 2 vCPU, 8 GB of RAM and 14 GB of SSD. On a public repository the same label gives 4 vCPU and 16 GB, free and unlimited. Windows matches Linux, and macOS on Apple silicon is 3 vCPU with 7 GB. The 14 GB of disk is the same on all of them, which is why disk-full failures appear on jobs with plenty of memory.

Related guides

References

Managed runners are one runs-on: line to try and one to undo. Latchkey is $0.0025/min at 2 vCPU. Start free → 30-day trial · No credit card