POC · June 2026 · GitHub Actions acceleration

Fresh CI runners should not rebuild the world.

By Yossi Eliaz · Principal Engineer, AI Systems at Incredibuild / islo.dev

This POC compares cache layers for GitHub Actions. In its runs, restoring Incredibuild's proprietary Build Cache cut a RocksDB build from 263s to 14s and a touched-source Tokio build from 38s to 13s, while Go, JavaScript and Docker were better served by GOCACHE, tool-native caches and BuildKit. Native caches are usually the fastest option when the same workspace is already warm.

C++ · fresh runner RocksDB 263s → 14s 18.8x with restored IB cache
Rust · fresh runner Tokio 46s → 13s fresh GitHub runner made warm
native vs IB touch test 38s → 13s dirty mtimes, same content

POC timings, not a controlled benchmark. Read the method note.

what to use when

The honest comparison.

The useful question is not "which cache is best?" It is "what got invalidated?" Incredibuild is compelling when compiler work is the expensive part and the runner starts clean.

Situation Use first Why
Fresh C/C++ or Rust runner Incredibuild Build Cache Restores compiler artifacts into a clean job.
Same workspace, no source changes Native build cache A hot local target/, GOCACHE, or incremental state is usually fastest.
Warm workspace, files touched Incredibuild Build Cache Dirty mtimes force native rebuilds; content-identical compiler work can still be reused.
Go builds GOCACHE + GOMODCACHE Go already has the right content-aware cache.
Docker image builds BuildKit cache Layer reuse is the real accelerator.
JS / TypeScript npm/pnpm + .tsbuildinfo + bundler cache Tool-native caches beat generic compiler-cache claims here.

the rule

Native warm state wins locally. IB helps when warm state disappears.

Native cache

Best when the same machine keeps its build directory and nothing changes.

Tokio Cargo warm: ~0s

Incredibuild Build Cache

Best when a fresh runner can restore content-addressed compiler work.

Tokio IB restored: 13s

Touch invalidation

When mtimes are dirty but contents are identical, native rebuilds; IB reuses.

Cargo touch: 38s · IB touch: 13s

measured in this POC

POC timings (not a controlled benchmark)

Timings from a June 2026 POC by Yossi Eliaz. Runner type, run count and logs are not published here, so treat the numbers as indicative.

ecosystem project / scenario baseline accelerated read
C++ facebook/rocksdb 263s 14s large IB win
C++ duckdb/duckdb 293s 16s large IB win
C++ llama.cpp 131s 13s IB strong
Rust tokio compile 46s 13s IB strong
Rust tokio full test 75s 43s IB helps compile slice
Rust tokio after touch Cargo 38s IB 13s clearest native-vs-IB contrast
Java Maven forked javac XL 15s 9s selective candidate
Go nektos/act 34s 0s native use GOCACHE
JS/TS TypeScript compiler 6s 4s native use tool cache
Docker BuildKit control 11s 3s use BuildKit cache
Docker moby/buildkit warm retry cold stream issue 2s warm use BuildKit cache

decision

What should this workflow cache?

Pick the workload shape. The answer should change by ecosystem.

runner context

Faster runners still need the right cache.

GitHub job Islo runner IB cache restore compiler build cache save

Whether you use GitHub Actions, faster hosted runners such as Blacksmith, or disposable runners on Islo, the question is the same: what state is worth restoring into a clean machine? Dependencies, native build state, BuildKit layers, and Incredibuild CI/CD acceleration compiler artifacts answer different parts of the job.

limits

What this POC does not show

Go and JavaScript/TypeScript builds showed little or no Incredibuild benefit here, and Docker speedups came from BuildKit layers, not compiler artifacts; use GOCACHE/GOMODCACHE, tool-native caches and BuildKit. A cold build of the full upstream moby/buildkit Dockerfile hit a BuildKit stream error, so only its warm retry is shown, next to a separate BuildKit control build.