CI that keeps up with your agents.
Change one line.
GitHub runners give each GitHub Actions job a fresh microVM on your servers or ours, next to a cache that already holds what the job needs. Agent pull requests get their own lane, so a thousand of them never starve the one you are waiting for.
- Isolation
- A fresh microVM per job, destroyed after
- Where
- Your servers, or the Frazer fleet by the second
- Cache
- Already warm: dependencies, build outputs, a disk per repository
- Agents
- Their own lane, cap and daily budget
# .github/workflows/ci.yml
jobs:
test:
- runs-on: ubuntu-latest
+ runs-on: frazer-8c
steps:
- uses: actions/checkout@v5
- run: go test ./... # caches already wired# .github/workflows/ci.yml
jobs:
test:
- runs-on: ubuntu-latest
+ runs-on: >- # bot PRs: agent lane · pushes: main
+ frazer-8c${{ github.event_name == 'pull_request' &&
+ (github.event.pull_request.user.type == 'Bot' &&
+ '-agent' || '') || '-main' }}# .github/workflows/release.yml
jobs:
release:
- runs-on: ubuntu-latest
+ runs-on: frazer-16c-release
steps:
- uses: actions/checkout@v5
- run: make release # reads dependencies only- A
- Five phases, every jobWait, start, cache, steps and upload, from GitHub’s timestamps and the VM’s own agent.
- B
- Why slower, from recordsCompared with the job’s median; causes named from events, never guessed.
- C
- Every cache restore shownWhich tier answered, how many bytes, how long, and who may write.
- D
- Results as dataThe Reviewer, the verifier and agents read results instead of scraping logs.
Most CI time is not your tests.
It is waiting, fetching and rebuilding.
Waiting for a runner
Runner fleets are sized for an average day; a burst of pull requests queues behind them.
Queue-driven scaling with a learned warm pool and overflow to the fleet; overcommit on your own servers.
A cold machine every time
Each job boots, installs toolchains and clones the repository from zero.
Warm microVMs from a signed image ring; a copy-on-write disk per repository with git objects and toolchains.
Downloading the same things
Every job fetches the same modules, packages and images from the internet.
A dependency proxy at the site, verified by checksums and lockfiles, shared by every job.
Rebuilding what did not change
No shared build cache, or one anybody can write to.
Content-addressed build outputs shared under write rules: protected branches write, pull requests read.
A cache that is far away or full
A remote cache with a size cap is slow to restore and evicts what you need.
A cache on the same servers, with quotas you set and fail-open behavior: an outage is a miss, never a failure.
Agents flooding the queue
Hundreds of agent pull requests a day land in the same queue as people’s.
Lanes with floors, caps and a daily budget that holds agent jobs instead of failing them.
A thousand agent PRs a day.
And yours still runs first.
Designed for 1,000+ agent pull requests a day per organization. Agents get their own lane below people, a floor so they never stop, a cap so they never take over, and a daily budget that holds their jobs in the queue rather than failing them.
One cache for CI, boxes and agents.
Shared widely, written carefully.
The same cache serves your runners, your engineers’ devboxes, agent sandboxes and serverless builds, so nothing is downloaded or compiled a hundred times. Only trusted builds write what others read, every entry is signed by its writer, and a poisoned entry is purged by writer in one command.
- Go modules
- GOCACHEPROG
- Docker · BuildKit
- actions/cache
- npm · pnpm
- PyPI · uv
- Bazel REAPI
- Gradle
- Turborepo · Nx
- sccache
Fresh, isolated, short-lived.
Every job.
A microVM per job
Its own kernel and Docker; never reused; nothing survives the job.
No long-lived tokens
Just-in-time runner registration; registry, secrets and cache through OIDC.
Egress you can read
An allow-list per pool, with a log of every destination.
Forks stay outside
Fork pull requests run only on untrusted pools; pull_request_target is refused on trusted ones.
Watched
Wedged runners are destroyed and the job re-run once; a second wedge opens an incident.
Same bytes everywhere
One workspace template builds the runner image, the devbox and the agent sandbox; “Debug in a box” opens a failed job.
The speed of hosted runners.
The control of your own.
| GitHub runners on Frazer | Typical hosted runner | Typical self-hosted runner | |
|---|---|---|---|
| A fresh VM for every job | Yes, a microVM | Usually | Rarely |
| Runs on hardware you own | Yes, or the Frazer fleet | No | Yes |
| A cache beside the runner, with quotas you set | Yes, four tiers | Remote, size-capped | Build it yourself |
| Rules for who may write the shared cache | Yes, by writer identity | By branch scope | Build it yourself |
| Lanes, caps and budgets for agent pull requests | Yes | No | Build it yourself |
| Why a job was slower, from records | Yes | Timestamps only | Build it yourself |
| Who patches images, scales and watches runners | Frazer | The vendor | Your team |
| Per-minute fee on your own servers | None | Not applicable | Varies by vendor |
Generic categories, not named products. No speed or cost figures here: the job page shows yours, from records.
GitHub Actions
github.com and GitHub Enterprise Server
GitLab
SaaS and self-managed runners
Buildkite
An agent per job
Forgejo and Gitea
Ephemeral runners
No per-minute fee
on servers you own.
On your servers, GitHub runners and Frazer Cache are part of the per-core server fee. On the Frazer fleet you pay $0.045 per vCPU-hour with 4 GiB per vCPU, billed per second, with no minimum and no rounding up.
See every price- Your servers
- Included in $1.50 per physical core per month
- frazer-4c
- 4 vCPU · 16 GiB · $0.003 per minute
- frazer-8c
- 8 vCPU · 32 GiB · $0.006 per minute
- frazer-16c
- 16 vCPU · 64 GiB · $0.012 per minute
- GPU runners
- The fleet GPU price plus a 4 vCPU runner
- Cache, your servers
- Included · uses your disks
- Cache, fleet
- $0.012 per GiB-month; no request or in-site egress fee
Code on Fir?
Frazer CI runs it natively.
GitHub runners runs GitHub Actions jobs for repositories that stay on GitHub. Repositories on Fir, Frazer’s version control, use Frazer CI instead: every task is keyed by the hash of its inputs, so a task whose inputs did not change is answered from its signed result before any machine starts. The tasks that run get their own microVM on Frazer Runners.
The two products share the price and the bill, never a host, a pool or a queue.
| GitHub runners | Frazer CI on Frazer Runners | |
|---|---|---|
| For | Repositories on GitHub | Repositories on Fir |
| Unit of work | A GitHub Actions job | A task with declared inputs, outputs and a key |
| What runs | Every queued job starts a machine | Only tasks whose inputs changed; the rest are cache hits |
| Source | A checkout into a warm disk | A read-only projection of the task’s inputs, no checkout |
| Results | Job records with phases and tests | A signed result per task, read by the merge policy |
| Price | $0.045 per vCPU-hour, per second | The same rate; a cache hit costs nothing |
GitHub runners, answered.
Do I have to change my workflows?
One line. Install the Frazer GitHub Runners app on your GitHub organization, create a pool and change runs-on to a Frazer size such as frazer-8c. actions/cache keeps working with no edits, and an optional onboarding pull request per repository writes the line with lanes and removes cache steps you no longer need.
How do you tell an agent’s pull request from a person’s?
By who opened it. The runs-on line sends pull requests opened by bot accounts to the agent lane, and a pool can also name agent branches or a list of agent accounts. The cache follows the same rule: an agent’s pull request writes only its own overlay.
Can a pull request poison the cache for everyone?
No. Only protected-branch CI and prebuilds write shared entries, and only from jobs that finish cleanly. Pull requests and agents write an overlay nobody else reads, forks write nothing, and release builds read dependencies only. Every entry records who wrote it and is signed, so a bad one is purged by writer in one command.
What happens when the agent lane runs out of budget?
Its jobs are held, never failed: they stay queued in GitHub, marked “Held: agent budget”, while people’s lanes keep running. Agents read the lane’s remaining budget and slow their pushes before it runs out, and you can raise the budget from the Runners overview with a plan.
Can I run GPU jobs or Android emulators?
Yes. Jobs that need whole GPUs or nested virtualization, such as Android emulators and VM tests, run in a full VM per job instead of a microVM. GPU runners run on your own GPU servers.