# How CloudX cut CI test times by 69% with a simple swap

> Replacing GitHub's setup-go action with a smarter caching strategy eliminated 86% of unnecessary test runs.
- Title: How CloudX cut CI test times by 69% with a simple swap
- Summary: Replacing GitHub's setup-go action with a smarter caching strategy eliminated 86% of unnecessary test runs. Parallel CI jobs need separate cache keys to…
- Keywords: cloudx, golang, github actions, continuous integration, actions/setup-go, cloudx-io/setup-go, ci performance, build cache, test cache, caching strategy, lukas schwab, peter downs
- Source: CloudX | Ad Infrastructure for the Intelligence Era — https://cloudx.ai/posts/setup-go
- Published: 2026-09-16T13:00:00+00:00
- Read time: 3 min
- Topics: cloudx, golang, github actions, continuous integration, actions/setup-go, cloudx-io/setup-go, ci performance, build cache, test cache, caching strategy, lukas schwab, peter downs
## A drop-in replacement for setup-go
CloudX built a new GitHub Action that cut test job runtimes by 69%. They're open-sourcing it so other teams can get the same speedup.
## The default action wastes effort
GitHub's official actions/setup-go makes parallel jobs interfere with each other. Backtesting shows 86% of the work it does is unnecessary.

> 86% of the work the default action does is completely unnecessary.
## Fast CI enables fast shipping
CloudX invests heavily in CI speed because reliable, quick tests let teams build fast without breaking things for customers.
## The 90-second goal
When you push code to CloudX, the goal is a clear answer on whether it builds, passes tests, and meets linter rules within 90 seconds.
## Algorithmic improvements matter most
CloudX already uses Warp Build for fast machines. As their test suite scaled, they realized actions/setup-go wasn't setting them up for success.
## The cache key is incomplete
The default cache key only includes OS, architecture, Go version, and go.mod hash. Most code changes don't modify any of these.
## Stale caches slow everything down
The first job run persists cache state. Until go.mod changes, every run loads that first value, which gets staler as you change code.
## Parallel jobs race each other
Multiple parallel jobs running setup-go race to write different cache states. The winner's cache might not help the other jobs at all.
## When lint wins, tests lose
If a lint job finishes first, it saves a cache without test results. Subsequent test jobs keep using that stale value and re-run tests unnecessarily.
## Go's toolchain caches are smart
The Go toolchain saves module downloads, build artifacts, and test results. It only recomputes when inputs actually change.
## Three caches work together
The module cache stores downloaded source code. The build cache stores package archives. The test cache stores test outputs and exit codes.
## GitHub Actions cache is different
GitHub's cache uses immutable key-value pairs. It only writes a new blob if the job succeeds and there was no exact key match initially.
## Job identity solves the race
cloudx-io/setup-go includes job identity in the cache key. Lint and test jobs now save and restore separate caches without conflicts.
## Save cache on every run
The new action writes a cache entry every time by including the run ID in the key. This preserves incremental work instead of discarding it.
## The real-world impact
When CloudX switched actions, median test runtime fell from 131 seconds to 41 seconds. That's a 69% improvement from one configuration change.

> cloudx-io/setup-go immediately cut test job runtimes by 69%.
## Fresh caches mean fewer tests
With the new strategy, the loaded cache is always fresh from the run before. Tests only run for packages genuinely modified by each commit.
## 86% reduction in test package runs
Backtesting 4,000 commits showed the new approach eliminated 86% of test package runs compared to the default action's behavior.
## Two downsides to consider
Cache blobs can grow large since they're saved more often. You may need expanded GitHub Actions cache capacity, though faster jobs offset the cost.
## Key takeaway

Parallel CI jobs need separate cache keys to avoid racing and loading stale data that forces unnecessary retesting.