CI baseline: what CI costs and how fast it ships, before the changes

The "before" numbers to compare against once the app is split and CI skips tests a PR can't affect.

Nov 1, 2026 · Oct 18–29 (before Fede's Oct 30 changes) · re-run with bin/ci-baseline

About 84% of the AWS bill is CI. Every CI machine carries a label AWS bills by, so this is measured, not guessed: $5,117 of October's $6,066 in usage before credits. Nearly all of October's $678 credit landed on CI machines, so after credits it is still about 83%.

NumberBefore
CI spend per day$100
CI spend per merged PR$0.69
PRs merged per day145
CI runs per merged PR5.6
Merge → live (median)54 min
Open → live (median)123 min
PRs that touch no product code11%

What this says about the plan. Splitting off the website would skip almost no CI: no PR in two weeks touched only website files. Tools, evals and docs-only PRs are about 9%, so path-scoped CI can skip at most about a tenth of PRs. The bigger levers are repeat runs (5.6 CI runs for every merged PR: 3.7 on the PR, 1.1 in the merge queue, 0.8 on main after) and a few slow steps.

The rest of the bill: the $411 "on-demand" line is $219 of full-price CI machines (used when cheap spare ones weren't available) plus $192 of data sent out of AWS; the $243 "VPC" line is the public IP address each runner gets. Vercel's bill can't be read from our login.

Day by day, top time sinks, sources and method

Per day (UTC)

AWS dollars are usage before credits. "CI $" = everything tagged Purpose=ci. Job-hours are estimated (runs × median machine-minutes per run, from 30 sampled runs of each kind). Grey rows are after Fede's Oct 30 04:14 UTC changes; Oct 31 is still filling in at AWS.

DaySpot EC2 $On-demand EC2 $CI $PR runsQueue runsMain runsJob-hrsMergesCI $/merge
10-18132217950438645$0.47
10-1959683495140111412134$0.62
10-20898122619204157535184$0.66
10-2133449232725719769$0.71
10-22907121640183123531165$0.73
10-23611089512137121422137$0.65
10-2441864395977831898$0.65
10-2544768346938328594$0.72
10-2666109445116581395125$0.75
10-2711523171866231188711219$0.78
10-2811722172987298210831263$0.65
10-299916143777234173655211$0.68
10-30133332021023318203865270$0.75
10-317010101538205153484183$0.55
Total1031167150079602427178167242197$0.68

Oct 18–29 only: CI $1,197 ($100/day), spot $827 vs on-demand $123, 1,744 merges, 9,728 runs (3.7 PR + 1.1 queue + 0.8 main per merge), ~448 machine-hours a day (estimate, ±30%).

Speed (PRs merged Oct 25–31)

WindowPRsOpen→mergeMerge→live med / p90Open→live med / p90Live within 1 h
Before Oct 30 04:14Z9426654 / 77123 / 3282%
After (2 days)4236922 / 3995 / 34823%

Minutes. The "before" row matches Fede's own baseline for the week of Oct 26 (125 / 54 / 2%), which checks the method. The "after" row is two days and already shows his changes working.

What merged PRs touch (Oct 18–31, 2,197 PRs)

Only touchesPRsShare
Website (src/app/(public), components/marketing, config/site-paths.json)00%
Internal tools (admin/dev, agents, api/agents, api/admin/dev, components/maestro)60.3%
Tools (scripts, evals, docs)1989.0%
CI plumbing (.github, scripts/ci)100.5%
A mix of the four above, no product code200.9%
Product code plus one of the above93642.6%
Product code only1,02746.7%

11 commits touched website files in the window, all alongside product code. PRs with 100+ files, or whose file list could not be read, count as mixed.

Where CI time goes (90 sampled runs, 30 per kind, before Oct 30)

Median machine-minutes per finished run: PR 38, merge queue 36, main 8. These are the noisiest numbers here (a 30-run sample moved the PR median between 20 and 38), so job-hours above are ±30%. Compare the per-run step medians below, not totals.

StepMedian min per run that ran itRuns (of 30)
PR · Unit Tests: run this shard19.616
Queue · Full set: full unit tests28.87
Queue · Full set: precise unit tests9.69
Queue · fail-fast watcher (a small machine that waits out the whole queue run)8.930
PR · Unit Tests: git checkout (shallow since Oct 31)4.330
Queue · Guard pins4.130
Queue · affected unit tests3.230
Main · Preflight wait-then-cancel3.130
PR · CI Checks: Mutation controls2.029

Mutation controls is the step to watch: 2.0 minutes on a typical PR run but 5.4 on average and up to 31, so a few PRs pay most of it (158 machine-minutes across 29 runs).

The AWS lines, explained

Sources

AWS Cost Explorer daily, UnblendedCost, Usage records, pulled Nov 1. GitHub: every ci.yml run by event in 6-hour windows; merged PRs per 2-hour window with file lists; Production deployments by vercel[bot]. Live = first Production deployment containing the merge commit (Fede's definition, ci-two-hours). Re-run: propflow-docs/bin/ci-baseline --from 2026-10-18 --to 2026-10-31 --split-at 2026-10-30T04:14:00Z.

PropFlow Docs