Introduction
GitHub Actions caches are an optimization, not permanent storage. When a cache is evicted manually or by normal platform policy, workflows fall back to full dependency restoration and suddenly become much slower. The best fix is not to panic at every cache miss. It is to make cache recovery predictable and keep builds resilient even when the hottest cache entry disappears.
Symptoms
- A workflow that was fast yesterday suddenly redownloads all dependencies
- Logs show
Cache not found for input keys - Manual cache cleanup or repository maintenance was performed recently
- Build time regresses sharply after a cache miss
Common Causes
- A frequently used cache entry was deleted manually
- Cache keys are too specific, so there is no useful fallback after eviction
- One monolithic cache is doing too much work and has no backup path
- The workflow implicitly depends on a cache hit to stay within acceptable duration
Step-by-Step Fix
- 1.Add restore keys so the workflow can fall back gracefully
- 2.Exact-key misses are normal. The important part is whether the workflow can still restore a near-match.
- uses: actions/cache@v4
with:
path: ~/.npm
key: ${{ runner.os }}-npm-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
${{ runner.os }}-npm-- 1.Split caches by purpose
- 2.Dependency downloads, build outputs, and tool caches should not all live in one giant cache key if they churn at different rates.
- 3.Measure how much time the cache really saves
- 4.If a single cache miss doubles build time, the workflow may need structural optimization rather than more cache reliance.
- 5.Avoid treating cache eviction as an outage
- 6.Caches help performance, but the workflow should still complete correctly without them.
Prevention
- Use restore keys for graceful fallback behavior
- Keep cache scopes focused instead of overly broad
- Monitor build duration so cache regressions are visible quickly
- Design workflows that remain correct and tolerable even on a cold cache