Swatinem/rust-cache: Dependency Caching for Rust CI
A GitHub Action that implements smart caching for rust/cargo projects
At a glance
- What is it?
- Swatinem/rust-cache is a GitHub Action that restores and saves selected Cargo dependencies and build artifacts for Rust workflows. Its defaults favor dependency-heavy projects with lockfiles and stable Rust toolchains, while custom keys and provider settings support more demanding CI matrices.
- Who is it for?
- Adopt Swatinem/rust-cache for Rust or Cargo workflows whose main cost is repeated dependency restoration and compilation, especially projects with a Cargo.lock file and a stable toolchain. Do not expect it to replace general-purpose build caching for application crates, and verify first whether your dependency ratio, lockfile policy, workspace layout, and matrix design match the README's documented assumptions.
- Can I use it commercially?
- Yes, with conditions. LGPL-3.0 is a weak copyleft licence: you can use it inside commercial and closed-source software, but if you distribute changes to its own files, you must publish those changes under the same licence.
- Is it still maintained?
- Yes. The repository received new commits within the last day.
- What is it written in?
- Mainly TypeScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Star history
- Swatinem/rust-cache1,940 ★ · +1
| Repository | 2026-10-16 | 2026-10-23 |
|---|---|---|
| Swatinem/rust-cache | 1.9k | 1.9k |
1 Stars in the last 7 days, measured from the daily GitHub snapshot. Compare with other projects
Editorial analysis
What Swatinem/rust-cache Optimizes
Swatinem/rust-cache targets a recurring cost in Rust CI: Cargo dependencies and their compiled artifacts often need to be reproduced when every workflow starts on a fresh GitHub runner. The action restores a cache before the build and saves a cleaned cache afterward. According to the README, it caches the dependencies of a crate, not the crate's own compiled workspace code by default.
That design makes the action most useful for repositories whose dependencies take longer to obtain or compile than the project's own source. Cargo registries, downloaded crate archives, git dependencies, compiler-installed binaries under ~/.cargo/bin, and dependency build artifacts can provide useful warm state across runs. The default cache also includes ~/.cargo and ./target, although the workspace crates in target are deliberately excluded from the most reusable portion of the cache.
The action is intended for maintainers of GitHub Actions workflows rather than developers running Cargo locally. It does not install Rust for you. The README requires the repository to be checked out and says that toolchain selection, whether performed by another action or by manual rustup commands, must happen before this action. This ordering matters because the cache key uses the current rustc version.
The default behavior is a sensible baseline, but it is not equally effective for every Rust repository. A library with only Cargo.toml and no Cargo.lock receives limited benefit because Cargo is expected to resolve the newest compatible dependency versions, which may not match cached artifacts. Stable Rust also produces more reusable results than an unpinned Nightly toolchain, since a moving Nightly version can invalidate the cache frequently.
How Swatinem/rust-cache Builds Cache Identity
The action derives a cache key from the GitHub job identity and the Rust environment. By default, add-job-id-key is set to true, so the built-in key includes the workflow job ID. A separate shared-key can replace the automatic job-based key, while key can be added to further distinguish jobs. The prefix-key, whose default is v0-rust, can be changed when maintainers want to start a new cache namespace.
When add-rust-environment-hash-key remains true, the key also incorporates the rustc release, host, and hash for all installed toolchains when available. The README lists hashes for Cargo.toml and Cargo.lock files found anywhere in the repository, root rust-toolchain or rust-toolchain.toml files, and root .cargo/config.toml files. It also includes compiler-related environment variables selected through env-vars. The default prefix list is CARGO CC CFLAGS CXX CMAKE RUST. Because matching is by prefix, RUST covers variables such as RUSTC, RUSTUP_*, RUSTFLAGS, and RUSTDOC_*.
Workspaces use newline-separated mappings of the form `$workspace -> $target`. If no target is stated, the default is target relative to the workspace. cache-targets controls whether workspace target directories are cached. Setting it to false leaves only the Cargo registry, which is appropriate when compiled workspace outputs are not worth retaining.
The cache-hit output is boolean and is set to true only for an exact cache hit. lookup-only provides a diagnostic mode: it checks the key and sets the output but does not restore the cache. This is useful for inspecting cache behavior without populating the runner.
Adding the Action to a GitHub Workflow
Start with the repository checkout, install the toolchain, and place Swatinem/rust-cache after those steps. The following is the README's basic example. The action is invoked as `Swatinem/rust-cache@v2`, and no separate action-specific installation command is documented because it is a GitHub Action used inside a workflow.
The checkout gives the action access to the repository manifests and configuration files. The rustup command installs the stable toolchain with a minimal profile. The action should see that toolchain and use its version in the cache key.
- uses: actions/checkout@v6
- run: rustup toolchain install stable --profile minimal
- uses: Swatinem/rust-cache@v2A real workflow must place these steps under the appropriate job and `steps` entries, as required by GitHub Actions syntax. After the action runs, the workflow can build with Cargo normally. The README does not require an explicit cache directory in this basic configuration because the defaults cover ~/.cargo and ./target.
For a matrix or selective-save policy, the README shows a `save-if` expression. This example saves only runs whose ref is `refs/heads/master`:
- uses: Swatinem/rust-cache@v2
with:
save-if: ${{ github.ref == 'refs/heads/master' }}That setting is appropriate when matrix jobs are additive or when maintainers do not want every branch run to populate the cache. It does not change the cache key itself. It changes whether a matching cache is saved.
Custom Keys, Providers, and Shell Execution
The action exposes controls for projects that need a different cache identity or execution environment. shared-key is intended to be stable across multiple jobs, while key adds a discriminator alongside the automatic job-based key. These controls are useful when the default environment hash does not capture a required distinction, although they also place the burden of key management on the workflow maintainer.
The cache-provider input can be either `github` or `warpbuild`, with `github` as the default. This changes the backend that provides the cache, not the Rust dependency policy. The repository's package.json includes `@actions/warpbuild-cache`, represented as the npm package `github-actions.warp-cache` at version `1.4.7`.
For environments such as Nix, cmd-format accepts a format string containing exactly one `{0}`. That placeholder is replaced with the `rustc` or `cargo` command. The README gives this example:
- uses: Swatinem/rust-cache@v2
with:
cmd-format: nix develop -c {0}This matters because invoking the system `rustc` and `cargo` directly would bypass the Nix shell required by the project. The format string is not a shell script in this example. It is a command template used for the two tools.
Other controls refine what is saved. cache-bin defaults to true for ~/.cargo/bin. cache-on-failure defaults to false. cache-all-crates and cache-workspace-crates default to false, preserving the action's dependency-focused behavior. save-if defaults to true. cache-directories allows additional non-workspace directories, while cache-targets false restricts saving to the Cargo registry.
What the Action Removes Before Saving
rust-cache does not persist everything it encounters. Before saving, it removes files in ~/.cargo/bin that existed before the action ran, such as an existing rustc binary. It also removes dependencies that are no longer used, anything that is not a dependency, incremental build artifacts, and build artifacts whose modification time is older than one week.
Workspace crates are not cached because the README says doing so is generally not effective. The action consequently sets CARGO_INCREMENTAL=0. This prevents the Rust compiler from spending time creating incremental artifacts that the cache policy would later discard. The tradeoff is intentional, but it means teams should not treat this action as a transparent layer over every Cargo build output.
The ~/.cargo/registry/src directory is also omitted. The README gives the reason: Cargo can recreate source directories from compressed crate archives more quickly than it can restore them from the cache. This cleanup keeps the cache focused on data that provides a meaningful restoration benefit.
The one-week age filter can also remove older build artifacts even if Cargo could theoretically reuse them. That choice limits cache size and discourages stale output, but it may matter for projects with unusual reproducibility or retention requirements. The README does not document a configurable retention period, so the documented policy is a one-week age threshold.
Practical Limits and Alternative Caching Approaches
The clearest limitation is the action's effectiveness depends on dependency reuse. For an application crate whose own code changes on every commit, the action may still restore dependencies but will not preserve the workspace crate's own compiled output. A project with a large dependency tree and a Cargo.lock file is a better fit than a library that continuously resolves new versions.
Nightly Rust is another boundary. The README says caches are tied to the Rust version and that an unpinned Nightly can throw away the cache every day. Pinning a specific nightly may improve reuse, but it also makes toolchain maintenance part of the project's cache strategy. Stable Rust is the documented more effective default.
A real alternative is GitHub's general Actions cache behavior applied to broader directories, such as a manually managed cache of target. The difference is scope and policy. A general cache can preserve more application-specific build output, but it does not provide rust-cache's dependency filtering, stale artifact cleanup, Rust environment hashing, Cargo manifest hashing, or automatic CARGO_INCREMENTAL=0 policy. The trade-off is control versus targeted reuse.
The project is not archived, and its last push was on 2026-10-14. That supports treating the repository as recently changed, but it does not establish that every configuration is bug-free. The available release history includes v2.9.2 on 2026-08-06, v2.9.1 on 2026-03-12, and v2.9.0 on 2026-03-12. Upgrade cost is therefore a matter of reviewing action major-version changes and workflow inputs, not installing a separate runtime package. The repository is licensed under LGPL-3.0, which is a licensing consideration for distribution and modification rather than a performance feature.
Editorial conclusion
Adopt Swatinem/rust-cache for Rust or Cargo workflows whose main cost is repeated dependency restoration and compilation, especially projects with a Cargo.lock file and a stable toolchain. Do not expect it to replace general-purpose build caching for application crates, and verify first whether your dependency ratio, lockfile policy, workspace layout, and matrix design match the README's documented assumptions.
Frequently asked questions
What should be configured before Swatinem/rust-cache runs?
Check out the repository and select the Rust toolchain first. The README says the action uses the current rustc version as part of its cache key, so toolchain setup should precede it.
Does Swatinem/rust-cache cache the compiled project itself?
By default, it caches dependency build artifacts rather than workspace crates. It does include ~/.cargo and ./target at a broad level, but the documented cleanup removes workspace crates, incremental artifacts, stale output, and unrelated files before saving.
When should cache-targets be set to false?
Set cache-targets to false when only the Cargo registry should be cached. This matches workflows that do not want workspace target directories persisted.
Can Swatinem/rust-cache use a Nix shell?
Yes. The cmd-format input accepts a command template containing exactly one `{0}`, which is replaced with `rustc` or `cargo`. The README gives `nix develop -c {0}` as the Nix example.
Which Rust projects benefit most from Swatinem/rust-cache?
The action is most effective when dependency and project-code compilation costs are substantial, the repository has a Cargo.lock file, and a stable Rust toolchain is used. Libraries without a lockfile have limited benefit according to the README.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/swatinem-rust-cache)Star history chart for your README
[](https://hysenlabs.com/projects/swatinem-rust-cache)Was this useful?