tempus.build
Self-hosted runners or managed: the real cost
For CI on GitHub Actions the cost question comes up sooner or later. Compare the instance price with GitHub-hosted’s per-minute billing, and on paper your own runners look cheaper. But an instance is only compute. The total cost of CI ownership is three line-items — compute, operations and risk — and the cloud price list shows only the first; the difference hides in the other two.
We build managed runners for GitHub Actions, so in this comparison we’re an interested party. That’s why the cases where self-hosted wins are named below too. Numbers here are published ones only; no Total Cost of Ownership — not just the price of the resource, but the operations, maintenance and risk over its whole lifetime. totals or “X% savings” — run your own on the calculator.
Three execution models
GitHub Actions CI has three models:
- GitHub-hosted — GitHub’s runners, billed per minute rounded up. Zero operations, but minute rounding and less control over the environment.
- Self-hosted — your own runners on your own hardware or cloud. Maximum control, but operations and security are entirely yours.
- Managed (tempus.build among them) — someone else’s runners as a service, but with the same
simplicity as GitHub-hosted: you change one
runs-online. You pay for execution; operations are the service’s job.
The rest is about the two poles: self-hosted and managed.
What self-hosted actually costs
The “instance for $N an hour” price tag covers only compute. Under it sits everything paid for in team time and idle capacity:
- Idle / always-on. Cloud instances and nodes are billed while running, not while executing a job. So you pay for the gap between builds and for headroom against peaks. CI is bursty by nature: a morning surge, quiet nights. That unevenness is what turns into paid idle time.
- Autoscaling. To avoid paying for a permanent peak, you need autoscaling. The standard OSS answer is ARC (actions-runner-controller), GitHub’s Kubernetes operator that autoscales self-hosted runners on demand. But that’s a cluster, the controller itself, runner scale sets, webhooks, RBAC — all of which you have to stand up, upgrade and maintain. Platform-team work, not a one-off install.
- Image build and patching. Someone builds the runner images, keeps toolchains and runtimes current, rebuilds for security patches and stops end-of-life versions from piling up. A continuous stream of work, not “set and forget”.
- Isolating untrusted code. CI runs someone else’s code — from PRs, from dependencies. Doing it safely takes VM-level isolation, Outbound network traffic from a runner — pulling dependencies and images. Clouds bill for it, and it has to be controlled for security. control, behavioural monitoring and A single-use runner for one job: created, runs, destroyed. Nothing survives the job boundary.. Self-hosting on shared, persistent runners opens the door to breakout and lateral movement. That’s not our take: GitHub itself advises against self-hosted runners on public repositories (opens in new tab) and recommends ephemeral runners — precisely because of untrusted code in PRs. (How that boundary works — in the Kata isolation deep-dive.)
- Cache infrastructure. Build speed rests on a dependency cache next to the runners (pull-through for npm/pip/docker, CAS). Without it every build pulls from the public internet — slower and pricier on Outbound network traffic from a runner — pulling dependencies and images. Clouds bill for it, and it has to be controlled for security..
- On-call. Uptime, upgrades, incidents and capacity all have an owner. A recurring human cost that a naive “by the VM price” comparison leaves out entirely.
Add these line-items up, and the “cheaper” from the instance-price comparison often disappears already at a mid-size team — one with no dedicated platform group to carry all this operational work.
How pricing works at tempus.build
Managed takes this operational cost off your team — images, patches, capacity and isolation are the provider’s job. In return you take on a dependency of your own (the provider’s uptime, a fixed shape catalogue, a trust boundary) — which is why the cases where self-hosted wins are named below.
The billing model changes too:
- Per second, no round-up. A 75-second job costs 75 seconds. GitHub-hosted rounds every job up to a whole minute — on short, frequent jobs that adds up.
- Execution only — no idle. You don’t pay for the gap between builds or for peak headroom: capacity and autoscaling are our concern, not a line on your bill.
- The delay to bring up a fresh environment (a VM or runner) before a job can start. A warm pool hides it at the cost of idle capacity. isn’t billed. The meter starts once the job is already executing; the seconds to boot a clean VM are on us.
- Prepaid — a spend ceiling is built in. The balance is topped up in advance and drawn down per second; new jobs don’t start at a zero balance, and running ones finish with an overrun of at most $1. There’s no surprise invoice at month’s end. The balance doesn’t expire.
- The price is baked into the label.
tempus-ubuntu-24.04-2coreis always$0.004/minand4core$0.008/min, in any repository. Whatever you pick inruns-onis what you pay — no hidden multipliers.
Two configurations are available today; 8- and 16-core are on request:
runs-on label | Resources | Rate |
|---|---|---|
tempus-ubuntu-24.04-2core | 2 vCPU / 8 GB | $0.004/min |
tempus-ubuntu-24.04-4core | 4 vCPU / 16 GB | $0.008/min |
2core is the same size as ubuntu-latest on private repositories and cheaper per minute ($0.004 vs
$0.006): the simplest way to switch for jobs that don’t need 4 cores. The 4-core rate ($0.008/min) is cheaper than a comparable GitHub-hosted larger runner; the balance is
in US dollars. GitHub’s exact prices and multipliers are in the
official docs (opens in new tab) (on public
repositories standard runners are free — this is about private ones). On small volumes private repos can
fit within GitHub’s included minutes — which is why we say “work it out on your volume” rather than
promising savings to everyone. What it comes to for you — on the calculator; there’s no
universal “X% cheaper”, it all depends on the pipeline.
The calculator runs on the assumptions you enter. Coverage runs on the facts: sign in to the platform with GitHub, install the GitHub App (opens in new tab) — and from your real runs after installation it shows what the same runs would have cost on tempus.build runners. Without moving a single job to our runners.
On top of that, spend control: organization budgets that alert or stop new jobs, spike notifications, optional auto-recharge. You can start with a welcome $5 on the balance — no card required (once per GitHub user, once you connect your first organization). That’s 625 minutes of a 4-core runner.
Comparison by axis
| Axis | Self-hosted | tempus.build (managed) |
|---|---|---|
| Billing model | for provisioned capacity (often always-on) | per second of execution, no round-up |
| Idle | you pay for idle and peak headroom | not billed |
| Operations | cluster, ARC, images, patching, on-call | on the service side (we run the fleet, images and patching) |
| Scaling | you build and tune it (ARC) | autoscaled on demand, within a per-organization concurrency limit |
| Cold start | you weigh a warm pool against its cost | managed; not billed |
| Isolation | your responsibility, easy to get wrong | VM per job + egress control + behavioural monitoring |
| Supply-chain | you attest images yourself | signed images + SBOM + SLSA, open-source |
| Cache | you build and run it | dependency cache in the same data-center region as the runners, over a private network |
| Time to value | days–weeks to a safe launch | one runs-on line, rollback the same |
Where self-hosted wins
Managed isn’t always the right answer. Self-hosted is stronger when:
- You need full control and your own hardware — GPU, ARM, Windows/macOS, your own images, special toolchains. tempus.build today is Ubuntu 24.04 x64 only, with two configurations: 2 vCPU / 8 GB and 4 vCPU / 16 GB.
- Strict data requirements — data residency, isolation in your own VPC or perimeter, air-gap. Your runners run where you say; a managed service is a third party inside the trust boundary.
- Steady 24/7 saturation. If a node is busy at nearly 100% around the clock, your own hardware at cost can beat any per-unit managed price. The per-second model wins on uneven CI, not on flat full utilisation.
- Vendor independence — no dependence on someone else’s uptime.
The dividing line: uneven CI + a small team + wanting zero operations → managed; steady 100% utilisation + strict residency + special hardware → self-hosted.
Trying tempus.build
Getting in and out is cheap by design:
- Switching in — one line.
runs-on: ubuntu-latest→runs-on: tempus-ubuntu-24.04-4core. The rest of the workflow doesn’t change. - Switching out — one line too. Put
ubuntu-latestback and you’re on GitHub-hosted again. Unused paid balance is refunded on request (welcome and bonus grants aren’t refundable); you can leave any time. - Isolation like a separate machine. Every job runs in its own single-use VM, destroyed on completion. The runner image is open-source (tempusbuild/runner-images (opens in new tab)) — you can build and check it yourself; how the isolation works is on the Security & isolation page and in the Kata isolation deep-dive.
- A GitHub organization is required. Runners currently serve private repositories in organizations; personal accounts and public repositories aren’t supported yet.
- A welcome $5 on the balance, no card — run your own pipelines and look at the real numbers before the first top-up.
Don’t take our word for it — work it out on your own volume and compare it with what your own operations cost you.