What Is a Cache Key in GitHub Actions?
Last updated
A cache key is the string GitHub Actions uses to find a saved cache. If a cache with an exactly matching key exists, it is restored; if not, the step reports a cache miss and your job rebuilds the data, then saves it under that key.
How it works
actions/cache takes a path to save, a key, and optional restore-keys. On restore it first looks for an exact key match. If none is found, it tries each restore-keys entry as a prefix and uses the most recent cache that starts with it. A prefix hit restores older data, which is usually better than nothing, and a new cache is saved under the full key at the end of the job.
Caches are immutable. You cannot overwrite a key, so a good key changes exactly when the cached content should change. The usual trick is hashing the lockfile.
Example
- uses: actions/cache@v4
with:
path: ~/.npm
key: npm-${{ runner.os }}-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
npm-${{ runner.os }}-
Here the key changes when the lockfile changes. If it does, the restore-keys prefix restores the previous cache, npm only downloads the difference, and a fresh cache is saved.
Building good keys
- Start with a stable prefix describing what is cached (
npm,cargo,gradle). - Add
runner.osand architecture if the contents are platform specific. - Add
hashFiles()of the files that define the content (lockfiles, build files). - Add a manual version number (
v2) so you can bust the cache on purpose.
The cache key builder generates keys for common stacks. See GitHub Actions caching for the full picture.
Common mistakes
- Keying on
github.sha. Every commit gets a new key, so you never hit the cache. - Hashing too little or too much. Hashing source files makes keys change constantly; hashing nothing makes caches go stale.
- No
restore-keys. One changed dependency causes a full rebuild instead of an incremental one. - Forgetting scope rules. Caches saved on a branch are visible to that branch and its base branch, not to sibling branches.
- Hitting size limits. Repositories have a total cache size cap and old entries are evicted. See cache limits.
Related terms
FAQ
Can I update an existing cache?
No. Keys are immutable. Change the key (for example via the lockfile hash) and a new cache is saved.
What does restore-keys do?
It provides fallback prefixes to restore the closest older cache when the exact key misses.
How do I clear a cache?
Delete it from the repository's Actions caches page or with the GitHub CLI, or bump a version string in the key.
Related
- Cache Cargo and Rust Builds in GitHub ActionsCache the Cargo registry, git dependencies and target directory in GitHub Actions with Swatinem/rust-cache or actions/cache, and avoid bloated caches.
- Cache Go Modules and Build Cache in GitHub ActionsCache Go modules (GOMODCACHE) and the build cache (GOCACHE) in GitHub Actions with setup-go or actions/cache. Keys, go.sum, and verifying hits.
- Cache Gradle Builds in GitHub ActionsCache Gradle dependencies and build cache in GitHub Actions with gradle/actions/setup-gradle or actions/cache. Keys, read-only PRs, cleanup and checks.
- Cache npm Dependencies in GitHub ActionsCache npm dependencies in GitHub Actions with setup-node or actions/cache. Working YAML, the right key, why not node_modules, and how to confirm a hit.