Speed Up Rust CI Beyond Dependency Caching
Summary
Pixel shares why rust-cache can still leave Rust CI rebuilding workspace crates: it excludes their artifacts and disables incremental compilation. The announcement compares GitHub-hosted runners with persistent machines, highlighting a tauri job that dropped from 246 to 53 seconds with Skipbox, which preserves the checkout and Cargo target directory between jobs.
DEV Community
Why rust-cache doesn't make your Rust CI fast (tauri: 246 s to 53 s)
Swatinem/rust-cache, the cache step in most Rust CI, saves your dependencies and deliberately leaves out your workspace crates. It also sets CARGO_INCREMENTAL=0. On GitHub's runners every job starts on a new VM, so every warm job, full cache hit and all, compiles your own crates again. No rust-cache setting makes that go away. What does is a target/ still there from the last job: Cargo then skips every crate that hasn't changed. Skipbox keeps it for you. Your job runs on your account's own machine, which keeps the checkout and Cargo's target/ between jobs. tauri's CI job took 246 s on GitHub and 53 s there, compiling none of its crates from the first warm run, with no change to its workflow but runs-on: skipbox, for a flat $39 a month. What rust-cache keeps, and what it leaves out From rust-cache's README and its source: What it caches: ~/.cargo (the registry, git dependencies, installed binaries) and ./target with your dependencies' build output. What it leaves out: "the workspace crates themselves are not cached". Before the save, its cleanup deletes everything in target/ that isn't a dependency, so your crates' artifacts are removed from target/ itself. Incremental compilation: the restore step exports CARGO_INCREMENTAL=0 for the rest of the job. When it saves: only when no cache has the job's key yet. The key comes from the toolchain, the environment, and your Cargo.lock and Cargo.toml. Your source files aren't part of it. On a fresh VM that adds up to one thing. A warm job restores your dependencies, then compiles your workspace crates and everything built on them, whole, every time. The mechanism, in tauri's logs tauri's test job runs five cargo test steps on Ubuntu, with rust-cache. Here are its warm runs, each a full cache hit (full match: true in the log): Warm run Compiling lines Cargo's build time Job GitHub 32 118 s 271 s Skipbox, fresh VM 32 62 s 146 s Skipbox, own machine, 1st warm run 0 about 1.5 s 53 s Skipbox, own machine, 2nd warm run 0 about 1.9 s 53 s The 32 lines are tauri's own crates, and two plugins built on them. The dependencies never show up: they come from the cache. Cargo's build time is the Finished … in times of the five steps, added up. The fresh VM has the own machine's CPUs and the same cache, and it compiled the same 32 crates as GitHub: its target/ held only what the cache restored. On the own machine, the first warm run already prints no Compiling line. Cargo only checked that nothing had changed, and each Finished took 0.2-0.7 s. The own machine's first warm run used to compile all 32 crates again (a 114 s job), because rust-cache's save after the cold run had deleted them from target/. Since 13 November 2026, own machines undo what rust-cache's restore and save delete from the disk, once the step ends. The cache it saves is the same, and your crates stay in target/. Job times: three Rust projects, seven others Real projects' own CI jobs at a pinned commit, the steps byte for byte; only the trigger and runs-on changed. One cold run, then two warm ones, on each side: GitHub: ubuntu-24.04, the standard runner of a public repository: 4 vCPU, 16 GB. Skipbox, fresh VM: a new VM per job from the production runner image, 4 vCPU and 8 GB, caches restored through Skipbox's cache. Skipbox, own machine: the same size on the same host CPUs, kept between jobs, with the keep-and-wipe that own machines run since 13 November 2026: the checkout and target/ stay, and what rust-cache deletes is put back. The Skipbox runs were on a Skipbox host, in a lab project kept apart from customers' machines. Times run from each job's start to its end, from GitHub's API. Each figure is the median of the two warm runs. The own machine's cold runs took 285 s for tauri, 161 s for ripgrep and 442 s for helix. Project GitHub Skipbox, fresh VM Skipbox, own machine GitHub ÷ own machine tauri 246 s (220, 271) 210 s (273, 146) 53 s (53, 53) 4.6× ripgrep 200 s (194, 206) 156 s (155, 156) 40 s (39, 40) 5.0× helix 330 s (293, 3...

Powered by Readybot.io