All writing

Why I Care About Fast CI

I’ve rarely heard an engineer say, “I love our CI.”

People have plenty of opinions about languages, editors, frameworks. CI? More often silence, or grumbling in Slack.

For me it usually comes down to the same thing: slow pipelines. That’s annoying on its own, but the bigger problem is what it does to how people work.


How I’ve Seen It Play Out

The web team

At one company, a full CI run took 45+ minutes. After a few sprints, nobody was opening small PRs anymore. People would stack a week of work on one branch so they “wouldn’t have to wait for CI as often.” Reviews got painful. Thousand-line diffs, approvals that were basically “looks fine,” bugs that a 200-line PR would have caught.

Flaky tests made that worse. Engineers would re-run the pipeline instead of reading the log. When red might mean your code or a broken suite, you stop trusting either.

iOS

On an iOS project, CI was slower still, and for reasons that felt hard to argue with. Every PR kicked off xcodebuild, spun up simulators, ran UI tests, and sometimes built for more than one destination. A green build could take an hour, and that was before you factored in queue time if three other PRs were ahead of yours.

So people drifted toward the usual workaround: “I ran it on my Mac, it’s fine.”

That holds up right until it doesn’t, because your machine has the right Xcode version, the right derived data, and the signing cert sitting in your keychain, and the runner has none of it. I’ve watched a PR sit green locally and fail on the runner because of a provisioning profile, a simulator that wouldn’t boot, or a UI test that passed on a fast M-series Mac and timed out on whatever the pipeline had available.

We only got PR feedback back to something tolerable after we stopped treating every check as mandatory on every push. UI tests moved to main. PRs ran unit tests and a single simulator destination. Caching Swift packages and derived data took the edge off cold xcodebuild. It didn’t turn into a three-minute pipeline, but getting from an hour-ish down to around twenty minutes was enough that people started waiting for green again.

When slowness meets flakiness

On both projects, slow CI and flaky CI pushed the team toward the same habit: small fixes got deferred until they were a project. I wrote about that compounding effect in Parkinson’s Law in Software Engineering. The pipeline stops being a safety net and turns into background noise.


Signs Your CI Is Too Slow

The big branches and rubber-stamp reviews are usually obvious once you’re in them. I also watch for:

  • People skip full local test runs because “it takes too long.”
  • Folks only run the tests they touched, hardly ever the whole suite.
  • Merge pressure: “can you approve while CI is still running?”
  • You’re budgeting for queue time, not just job duration.

I don’t think there’s one magic number for “fast enough.” Look at behavior. If people are planning around CI instead of using it, you’re already in trouble, whether the pipeline takes 20 minutes or two hours.


Treat CI Slowness Like a Bug

The shift that helped me most was treating slow CI like a production issue.

It costs real time. It nudges people toward bigger changes and weaker reviews. On bad weeks, that cost beats some user-facing bugs you’d normally drop everything to fix.

If you want to actually improve it:

  1. Find the slowest step first. On iOS that’s often simulator UI tests or cold xcodebuild with no cache. On web it’s usually integration tests or Docker builds done one after another. Measure before you optimize.
  2. Set a goal from where you are now. “Cut PR feedback from 45 minutes to under 15” beats copying a number from someone else’s blog post.
  3. Spend real time on the pipeline. Cache dependencies and derived data. Run jobs in parallel. Split the suite so PRs get a fast path and main gets the full run.
  4. Let engineers change it. The people waiting on CI should know what it runs and be able to trim or fix it. “Throw it over the wall to DevOps” is how pipelines turn into black boxes.

When teams actually invest here, the first wins are usually boring. Caching and parallel unit tests might shave 20+ minutes off before anyone rewrites a test. Quarantining flaky UI tests so red means something again is often the second win.


Speed Isn’t the Only Goal

You can also make CI worse by chasing a timer.

Drop integration tests to hit a target and you’ll ship regressions. Cache too aggressively without knowing when to bust the cache and you get false greens. On iOS there’s a real floor: simulators, signing, device matrices, UI tests that need a Mac runner. You’re not getting a meaningful iOS pipeline down to three minutes without cutting something that matters.

What I want isn’t a vanity metric. I want feedback fast enough that people trust it and actually wait for it, without dropping the checks that keep users from getting a broken build.


The shared tool that gets ignored

I’ll happily spend an evening tuning my editor or shell config. The CI pipeline is the shared tool the whole team uses every day, and it often gets ignored until it’s on fire.

A good pipeline won’t fix a broken team culture by itself. But it does make smaller PRs feel worth it again, and it makes the little cleanups worth doing.

I still rarely hear anyone say they love their CI. I think that’s fixable, but it takes treating pipeline speed like it matters to the people stuck waiting on it, not just the infra budget.

Next time there’s room on the sprint board for tech debt, ask whether CI belongs there, not as a vague ticket nobody owns but as a number you’d actually track and try to bring down.

Email address copied [email protected]