The 8 levers
To make CI faster, attack one or more of these in roughly priority order:
- Parallelize jobs — independent work in parallel jobs collapses wall-clock.
- Cache aggressively — install, build output, Docker layers, model weights.
- Use larger runners — for CPU-bound steps, double the cores often halves the time. Linear cost, sub-linear time? Win.
- Skip what doesn't apply — paths filters, conditional jobs.
- Concurrency cancel-in-progress — kill stale runs.
- Smaller test subsets on PR — smoke on PR, full on main.
- Faster install tooling — uv vs pip, pnpm vs npm, cached docker buildx.
- Test sharding — split slow suites across runners.
Measure, don't guess
Before optimizing, look at the run timeline. The longest step is your candidate. GitHub's run page shows per-step duration; gh run view --log gives you raw timings. Optimize the worst, re-measure, repeat.