Skip to content
Dev Tools Intermediate Tutorial

Speed Up Rust Compile Times with sccache, mold, and cargo-nextest

Wire a compilation cache, a faster linker, and a parallel test runner into your Rust project.

Lenn Voss
Lenn Voss
Cloud & Infrastructure Writer · Aug 6, 2026 · 5 min read
Speed Up Rust Compile Times with sccache, mold, and cargo-nextest

What you'll build

You'll take an existing Rust workspace and cut its clean-build, rebuild, and test times by wiring in three tools: sccache (a compilation cache that survives cargo clean and fresh CI runners), mold (a drop-in faster linker), and cargo-nextest (a parallel, process-per-test runner). Everything lands in two config files and three installed binaries — zero source changes.

Prerequisites

  • OS: Linux x86_64 (commands shown for Ubuntu 22.04+/Debian 12). sccache and nextest also work on macOS and Windows; mold produces ELF output only, so macOS readers should skip step 3 — Apple's linker and Rust's bundled rust-lld already cover you.
  • Rust: a stable toolchain via rustup. Verified against Rust 1.97.1.
  • clang: any recent version (sudo apt install clang) — it's the linker driver that hands off to mold.
  • Tool versions verified for this tutorial: sccache 0.17.0, mold 2.41.0, cargo-nextest 0.9.143.
  • A Rust project with a test suite. Every command below is project-agnostic, so use a real one — the bigger the dependency tree, the bigger the win.

1. Record a baseline

You can't claim a speedup you didn't measure. From your project root:

cargo clean
time cargo build
time cargo test

Write both numbers down. Also note the incremental case — touch one file, time cargo build again — since that's the build you do a hundred times a day.

2. Wire in sccache

sccache wraps every rustc invocation and caches the output keyed on the exact inputs, so recompiling the same crate — after a cargo clean, in a second checkout, or on a CI runner with a shared backend — becomes a cache read.

Install it:

cargo install sccache --locked

(Prebuilt binaries exist on the GitHub releases page, and brew install sccache works on macOS, if you'd rather not compile it.)

Then tell cargo to route every compile through it, in ~/.cargo/config.toml:

[build]
rustc-wrapper = "sccache"

Two limitations to know, straight from the docs: sccache can't cache incremental compilation, and it can't cache crates that invoke the linker (bin, dylib, cdylib, proc-macro). In practice that's fine locally — cargo only compiles workspace members incrementally, so your dependency tree (usually 90% of a clean build) caches, while your own crates pass through untouched. In CI, set CARGO_INCREMENTAL=0 so workspace crates become cacheable too.

Prime the cache and watch it pay off:

cargo clean && cargo build        # cold: all cache misses, roughly baseline speed
cargo clean && cargo build        # warm: dependency compiles come from cache

The second run is where clean-build time collapses.

3. Switch the linker to mold

Linking is single-file-dominated and runs on every rebuild, which makes it the bottleneck for the edit-compile-test loop. mold parallelizes it aggressively.

One honest caveat first: since Rust 1.90, x86_64-unknown-linux-gnu already defaults to LLD, which the Rust project measured at 7× faster linking than GNU ld. So the dramatic numbers in older mold blog posts assume a slower starting point than you have today. mold still beats LLD, but the margin grows with binary size — measure on your project.

Install and configure:

sudo apt install mold

(Distro packages lag upstream a bit; build from source per the mold README if you want 2.41.0 exactly.)

Add to your project's .cargo/config.toml (create the .cargo directory if needed):

[target.'cfg(target_os = "linux")']
linker = "clang"
rustflags = ["-C", "link-arg=-fuse-ld=mold"]

clang is used as the driver because it accepts -fuse-ld unconditionally; GCC only accepts mold as a value from 12.1.0 on. To try mold once without touching config, prefix any build with mold -run cargo build.

4. Run tests with cargo-nextest

nextest runs every test in its own process and schedules them in parallel across all cores, which is both faster than cargo test's per-binary threading and better isolated — one segfaulting test can't take down its siblings.

Install a prebuilt binary (compiling it via cargo install cargo-nextest --locked also works):

curl -LsSf https://get.nexte.st/latest/linux | tar zxf - -C ${CARGO_HOME:-~/.cargo}/bin

Run your suite:

cargo nextest run

One gap by design: nextest can't run doctests (a stable-Rust limitation), so keep cargo test --doc as a separate step if you have them.

Verify it works

sccache — after the two builds from step 2:

sccache --show-stats
Compile requests                    312
Compile requests executed           290
Cache hits                          275
Cache hits (Rust)                   275
Cache misses                         12
Cache hits rate                   95.82 %
Cache location            Local disk: "/home/you/.cache/sccache"
Version (client)          0.17.0

Your numbers will differ; the line that matters is a high Cache hits rate after the second clean build. (sccache --zero-stats resets counters between experiments.)

mold — linkers sign their work in the binary's .comment section:

readelf -p .comment target/debug/<your-binary> | grep mold
  [    2c]  mold 2.41.0 (compatible with GNU ld)

Any mold line means the switch took.

nextest — you should see per-test lines and a summary:

    Starting 48 tests across 6 binaries
        PASS [   0.011s] myapp config::tests::parses_defaults
        ...
------------
     Summary [   0.982s] 48 tests run: 48 passed, 0 skipped

Finally, rerun your step 1 timings and compare.

Troubleshooting

error: linker 'clang' not found — rustc can't find the driver named in your config. sudo apt install clang, or if your GCC is 12.1+, delete the linker = "clang" line and let the default cc pass -fuse-ld=mold.

clang: error: invalid linker name in argument '-fuse-ld=mold' — clang couldn't locate mold on PATH. Install it (step 3) or point at it absolutely: rustflags = ["-C", "link-arg=-fuse-ld=/usr/local/bin/mold"].

sccache shows zero cache hits — expected on the first cold build; hits only appear when the same compile happens twice. If a second clean build still misses, check --show-stats for non-cacheable calls: incremental compilation is the usual culprit, so confirm CARGO_INCREMENTAL=0 in CI, and remember linker-invoking crates never cache.

error: no such command: 'nextest' — the binary isn't on cargo's PATH. Confirm it landed in ~/.cargo/bin (the tar in step 4 must extract there) and that ~/.cargo/bin is in your PATH.

Next steps

Take the same wins to CI: sccache's GitHub Actions cache backend (SCCACHE_GHA_ENABLED, see docs/GHA.md in the repo) or an S3/Redis backend shares one cache across your whole team, and taiki-e/install-action@nextest installs nextest in one workflow line. Profile what's still slow with cargo build --timings — it renders an HTML report showing which crates serialize your build. And dig into nextest's config for CI sharding (--partition), automatic retries for flaky tests, and JUnit output.

Sources & further reading

  1. sccache - Shared Compilation Cache — github.com
  2. sccache docs: Rust usage and caveats — github.com
  3. mold: A Modern Linker — github.com
  4. cargo-nextest documentation: Installation and running — nexte.st
  5. Faster linking times with 1.90.0 stable on Linux using the LLD linker — blog.rust-lang.org
  6. Rust Versions — releases.rs
Lenn Voss
Written by
Lenn Voss · Cloud & Infrastructure Writer

Lenn writes about cloud platforms, Kubernetes internals, and the infrastructure decisions that quietly make or break engineering organizations. Based in Berlin's vibrant tech scene, they have a talent for turning dense platform-engineering topics into prose that people actually finish reading.

Discussion 0

Join the discussion

Sign in or create an account to comment and vote.

No comments yet

Be the first to weigh in.

Related Reading