Skip to content
compiler.dev

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

  1. Start with a stable prefix describing what is cached (npm, cargo, gradle).
  2. Add runner.os and architecture if the contents are platform specific.
  3. Add hashFiles() of the files that define the content (lockfiles, build files).
  4. 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.

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.