Every managed runner's homepage says faster. Saying it is easy. We moved our own repos to our own runners and then measured it in public, on real workloads, with a repo you can fork and rerun. Claims are marketing; runs are receipts. Here are the receipts.
In October we moved the benchmark to three heavier workloads that look like real CI: a Rust test and lint run, a TypeScript monorepo install and typecheck, and a production Docker image. Each one is a pinned commit of a real open-source project, runs five times per runner on identical jobs, and we report the median.
Everything below comes from github.com/buildpulse/runner-benchmarks, measured on October 23, 2026. If you get different numbers, let us know by opening an issue.
Speed, measured
Both runners at 4 vCPU. Median seconds of the timed steps, and each number links to its run:
| Workload | GitHub ubuntu-latest | BuildPulse x64-4x | Faster | Time saved |
|---|---|---|---|---|
| Rust test and lint (spotify-player, cargo test + clippy) | 231 s | 112 s | 2.1x | 52% |
| TypeScript install and typecheck (opencode, bun install + turbo typecheck) | 123 s | 64 s | 1.9x | 48% |
| Docker image build (PostHog, no cache) | 787 s | 588 s | 1.3x | 25% |
The pattern holds from August: the more of the job is raw compute, the bigger the gap. Rust and TypeScript are close to twice as fast. A Docker build spends more of its time writing layers to disk, so the gain is smaller. The Docker build runs on our docker-builder 4x runner, the label we recommend for image builds, and both sides build with buildx and no cache.
The first round, in August, used hugo and vuejs/core (a Docker build, a Node install and test run, and a Go compile). Those workflows are still in the repo, and our CircleCI and Semaphore comparisons run them.
A newer AMD EPYC generation is most of the story. That claim is measurable too, so we measured it.
The hardware, measured
Same sysbench and fio commands on both runners, straight from the hardware workflow:
| Probe | GitHub ubuntu-latest | BuildPulse x64-4x | Difference |
|---|---|---|---|
| CPU | AMD EPYC 7763 (Zen 3, 2021) | AMD EPYC 9R45 (Zen 5, 2025) | 2 generations |
| sysbench CPU (events/s, all cores) | 8,186 | 22,178 | +171% |
| sysbench memory throughput | 12.0 GB/s | 27.8 GB/s | +133% |
Zen 5 is the newest server generation AMD makes; GitHub's fleet is two generations behind it. The full probe set, including disk, is in the public workflow logs; run it yourself on any runner.
The cache your next build actually hits
Cold-vs-warm is where runner infrastructure differences stop being subtle. The docker-cache workflow builds hugo's Dockerfile twice, and the warm build runs on a fresh machine, so any difference between cold and warm comes from the cache infrastructure and nothing else. The GitHub side uses GitHub's own recommended caching for docker builds. On BuildPulse there is nothing to set up: docker-builder machines keep each customer's layer cache between builds, so your second build is fast without a single line of cache configuration in the workflow.
| Cold build | Warm rebuild, fresh machine | |
|---|---|---|
| GitHub + gha cache | 276 s | 3 s |
| BuildPulse docker-builder | 145 s | 1 s |
Cold builds finish in about half the time. Warm rebuilds of this image are near-instant on both: hugo's layer cache is small enough that GitHub's remote cache restores it fine. The differences that matter show up in what surrounds that number.
- Zero configuration. No cache-from, no cache-to, no scope keys in your workflow.
- No 10 GB per-repo cache quota, no eviction fighting other caches in the repo.
- Package-manager caches inside the build (
RUN --mount=type=cache) survive between builds, because the cache is the build machine's own storage. Remote cache backends drop these.
Cost per build
Our per-minute rate is 33 percent below GitHub's at 4 vCPU ($0.008 against $0.012). You also buy fewer minutes, because the same job finishes sooner. Together, job time multiplied by each side's per-minute rate:
| Workload | GitHub | BuildPulse | Saved |
|---|---|---|---|
| Rust test and lint | $0.0462 | $0.0149 | 68% |
| TypeScript install and typecheck | $0.0246 | $0.0085 | 65% |
| Docker image build | $0.1574 | $0.0784 | 50% |
In dollars at 4 vCPU, every $100 of these builds on GitHub Actions costs about this much here: Rust $32, TypeScript $35, Docker $50. The full rate table is on buildpulse.io/pricing.
Why BuildPulse
The same jobs finish in 25 to 52 percent less time, on CPUs two generations newer, with a docker cache that works without configuration. In practice: a $1,000 a month GitHub Actions bill becomes roughly $320 to $500 for the same workloads, or the same budget runs 2 to 3 times the CI. You do not have to take our word for any of this: every number above links to a public run, and the harness is a repo you can fork and point at your own workloads.
Then there is the part no benchmark table shows, and the reason we built runners at all: every job on BuildPulse runners feeds the same platform's flaky-test detection. A red build tells you whether the failure is your code or a test with a known failure history before an engineer spends twenty minutes finding out manually. Faster minutes are table stakes; knowing which failures matter is the product.
.github/workflows/ci.yml
jobs: test:- runs-on: ubuntu-latest+ runs-on: bp-ubuntu-latest-x64-4x
That is the entire change for most workflows. A few workflows also need a setup action for tools our deliberately minimal image does not preinstall (in our own migration of thirteen repos, exactly three: composer, sbt, and Chrome). The full step-by-step guide is its own post.