Self-hosting CI gets harder every month | Blacksmith
Self-hosting CI gets harder every month
More code is being written than ever. CI volume is outgrowing infrastructure that used to work.
CI demand comes in bursts
A busy hour can leave jobs waiting, while a quiet one leaves machines idle.
Demand changes by the minute
A fleet sized for a typical hour can run out of machines when everyone pushes at once.
Bursts fill the queue
When a burst uses your available machines, other jobs wait for the autoscaler.
Idle machines cost money
You’re paying to keep machines ready, even when there are no jobs to run.
Why do jobs queue even with autoscaling?
- Jobs queue while machines boot
Demand jumps 4,000 vCPUs in five minutes. The autoscaler requests more machines, but none are online yet. 2,900 vCPUs of work sit in the queue. - Capacity catches up, late
New machines come online about three minutes after they’re needed. By then, demand has moved again. - Capacity drops late, you pay for it
Demand drops 12,000 vCPUs in five minutes. Capacity stays up for the 15-minute cooldown. That leaves 15,000 vCPUs running with nothing to do.
What it costs
You wait for machines
Jobs queue while each new machine starts and registers, which can take minutes.
"Our self-hosted runners were having autoscaling issues and they’d be in queue for 5, 10 minutes. People would report that."
— LangChain, self-hosted runners on GCP
You compete for capacity
The instance type you request can be out of stock, or you hit your vCPU quota. Either way, jobs stay queued.
"At the start of the year our self-hosted CI runner cluster would get m8 instances with a 90 percent success rate. It has dropped to 15 percent"
— Arian van Putten
You pay to avoid waiting
A warm pool skips the wait, but you keep paying for it when CI load drops.
"I got sick of spending the time babysitting the warm pool and just took the scaling policies out, but it means you’re provisioning for the peaks."
— Megaport, self-hosted runners on AWS
You lose spot machines mid-job
Spot instances are cheap until they’re reclaimed, and your job is cut off mid-run.
"I’m spending a whole quarter on it. If this ends up being cheaper than all of this, then I can spend my time on actually useful measures instead of tuning a GitHub runner thing."
— Amplitude, ARC + Karpenter on Kubernetes
The biggest cost is your team’s time
You pay for machines and the time your team spends maintaining them.
CI infra backlog
GitHub
- Handling API rate limits
- Updating runner versions
- Handling webhook delivery
Capacity
- Tuning autoscaling policies
- Asking AWS for quota bumps
- Isolating noisy neighbors
- Spot interruptions killing jobs mid-run
Images and caches
- Upgrading toolchains
- Patching base image CVEs
- Maintaining OS images
- Managing Docker and runtime caches
Network
- Avoiding Docker Hub limits
- Maintaining egress allowlists
Observability
- Tracking queue times
- Attributing job costs
- Measuring CPU and memory
Customer data
How long do jobs wait for a machine?
Queue time
How long a job waits between being queued and a runner picking it up.
P95, Time within which 95% of jobs started: Self-hosted: 1m 8s to 1m 19s; Blacksmith: 10s to 29s.Jobs waiting over a minute
The share of jobs that waited more than 60 seconds for a runner.
Self-hosted: 5.51% to 7.68%; Blacksmith: 0.27% to 2.37%.
Why Blacksmith
Keep your workflows, let us manage everything else
Install the GitHub App and move the jobs you pick with a one-line change. Switching back is a simple revert.
- runs-on: [self-hosted, linux, x64]
+ runs-on: blacksmith-4vcpu-ubuntu-2404
What stays in GitHub
- Workflows
Your workflow files stay in your repo. You choose which jobs move to Blacksmith. - Secrets
Secrets stay in GitHub and work with Blacksmith runners just as they do with your self-hosted runners. - Permissions
Who can run what, branch protection, and required reviews all stay in GitHub.
What moves to Blacksmith
- Runners
High-performance, purpose-built compute with unlimited concurrency at no extra cost. - Caches
Dependencies, Docker layers, container images, and Git checkouts are cached with zero configuration. - Operations
We patch CVEs in base images, keep toolchain and dependency versions current, and pull unhealthy machines before your jobs land on them. - Observability
Every job’s logs, resource usage, and test failures in one place, with no agents to install.
Stop managing your own caching
Zero-config caching skips as much of every job as possible. What’s left runs on the fastest, purpose-built infrastructure.
Cache & reuse
- Git cache
Checkout: 18s without cache, 3s with cache. - Container images
Initialize containers: 12s without cache, 9s with cache. - Machine images
Install dependencies: 42s without cache, 7s with cache. - Build cache
Compile and test: 48s without cache, 8s with cache. - Docker layers
Build and push: 54s without cache, 9s with cache.
How did job runtimes change after moving to Blacksmith?
Job runtimes
- Application builds
Blacksmith: 1m 20s, Self-hosted: 1m 54s, 30% less time. - Package unit tests
Blacksmith: 1m 23s, Self-hosted: 2m 35s, 46% less time.
Blacksmith by the numbers
- 100M+ completed jobs a week on Blacksmith runners.
- 44K concurrent vCPUs at one customer’s peak.
- 5 data centers across the US and EU.
- 11 PB+ of Git, Docker, and dependency caches kept warm.
- Unlimited concurrency, at no extra cost.
- Flat per-minute pricing.