Title: GitHub Actions cache: how actions/cache works and fails
URL: https://codemany.com/articles/github-actions-cache
Description: GitHub Actions cache saves files between jobs with actions/cache. Learn keys, limits, when caches miss, how to clear them, and how a local cache helps.
All pages as Markdown: https://codemany.com/llms.txt

---

[Home](https://codemany.com/) › [Articles](https://codemany.com/articles)

# GitHub Actions cache, explained

The GitHub Actions cache saves files between workflow runs, so a job doesn't download the same things again. You turn it on with the `actions/cache` step: a key names the cache, and a path says what to save.

## What the GitHub Actions cache does

Every job on a GitHub-hosted runner starts on a clean machine. So each run fetches your packages again: npm modules, Go modules, pip wheels and more. That takes time.

GitHub Actions caching fixes part of that. At the end of a job, the cache step uploads a folder to GitHub. The next run downloads it back before your build starts. A download of one big file is often faster than many small installs.

Here is a simple cache step with `actions/cache` v4:

```
- uses: actions/cache@v4
  with:
    path: ~/.npm
    key: npm-${{ runner.os }}-${{ hashFiles('package-lock.json') }}
    restore-keys: |
      npm-${{ runner.os }}-
```

Many setup actions can do this for you. For example, `actions/setup-node` has a `cache: npm` input.

Cache only what is slow to make and safe to share. Good choices are package downloads and build tool caches. Don't cache secrets, and don't cache your build output if you need a clean build each time.

## How cache keys and restore-keys work

The **key** is the cache's name. Put a hash of your lock file in it. When the lock file changes, the key changes, and a new cache is saved.

The steps run in this order:

1. Exact match
   GitHub looks for a cache with the exact key. If found, it is a hit.
2. Prefix match
   If not, it tries each `restore-keys` prefix in order. It takes the newest cache that matches.
3. Save
   If there was no exact hit, the step saves a new cache under the full key when the job ends.

Caches are also tied to branches. A run can restore caches from its own branch and the default branch. A pull request can also use its base branch. It can't use a cache made on a sibling branch.

## Cache limits and eviction

GitHub caps the cache for each repo. As of November 2026, the default is 10 GB per repo, and admins can raise it. When the repo is full, GitHub deletes the caches that were used longest ago first. It also removes any cache entry not used in over 7 days.

These numbers change. Check [GitHub's caching docs](https://docs.github.com/en/actions/reference/workflows-and-actions/dependency-caching) for today's limit.

## Why your cache misses

A miss means the job does the full install again. Common causes:

- **The key changed.** A new lock file hash, OS or tool version makes a new key.
- **Wrong branch.** A feature branch can't see a cache saved on another feature branch.
- **It was evicted.** Big caches push old ones out. Unused ones expire after 7 days.
- **The job failed.** The cache step saves at the end, so a failed job may save nothing.
- **Wrong path.** The `path` must match where the tool really writes files.

A cache that hits can still be slow. Uploading and downloading a large file takes time on every run. If your builds still drag, see [why GitHub Actions is slow](https://codemany.com/problems/github-actions-slow).

## How to clear the cache

Sometimes a cache goes bad, and you want a clean build. There are two ways to clear the GitHub Actions cache.

- **On GitHub.** Open your repo, go to the **Actions** tab, then **Caches** in the sidebar. Delete the entries you don't want.
- **From the command line.** Use the GitHub CLI:

```
gh cache list
gh cache delete npm-Linux-1a2b3c   # one cache, by key
gh cache delete --all              # every cache in the repo
```

A quick trick also works: add `-v2` to your key. Old caches no longer match, and they expire on their own.

## A local cache on your own machine

On a [self-hosted runner](https://codemany.com/docs/guides/self-hosted-runner), the job runs on your computer. `actions/cache` works there as well. But your machine can also keep files close by, with no upload at all.

Codemany gives each job a fresh, single-use runner on your Mac or Linux machine. Some things still stay warm between jobs:

- **Tool cache.** Downloads from `actions/setup-go`, `setup-node`, `setup-python` and other `actions/setup-*` steps stay in `~/.codemany/toolcache`. It is pruned past 20 GB.
- **Go modules on Linux.** Jobs get a `GOPROXY` that points at a mirror on the machine. If the mirror is down, Go falls back to proxy.golang.org.
- **Docker Hub on Linux.** BuildKit's Docker Hub pulls go to a local mirror first. Read [Docker layer caching in GitHub Actions](https://codemany.com/articles/docker-layer-caching-github-actions).

Your own settings always win. If your workflow sets `GOPROXY`, Codemany leaves it alone. More on this in [local cache](https://codemany.com/features/local-cache).

## Questions

### How big can the GitHub Actions cache be?

GitHub caps it per repo and evicts old entries. Check GitHub's docs for today's limit.

### How do I clear the GitHub Actions cache?

Delete entries in the repo's Actions › Caches page, or with the gh cache delete command.

### Does actions/cache work on self-hosted runners?

Yes. On Codemany, the tool cache also stays warm on the machine, and Linux machines keep local package mirrors.

## Related

Read next: [local cache](https://codemany.com/features/local-cache), [Docker layer caching](https://codemany.com/articles/docker-layer-caching-github-actions), [slow GitHub Actions](https://codemany.com/problems/github-actions-slow) and [what a self-hosted runner is](https://codemany.com/docs/guides/self-hosted-runner).

[Start a 14-day trial](https://codemany.com/docs/get-started) No card needed. $20 a month for 2 machines after that.
