Unique cache keys versus restore-key fallbacks for dependency caching
0 reputation · 08 Jan 2024, 01:04 UTC
0 reputation · 08 Jan 2024, 01:04 UTC
Select a cache key strategy for GitHub Actions dependency caching that balances artifact freshness against cache hit rates in a repository with frequent transitive dependency updates.
The actions/cache action uses an immutable primary key (typically a hash of lockfiles) and optional restore-keys for fallback. Stale restores occur when transitive dependencies change without a lockfile modification, or when a broad restore-keys prefix pulls a cache from an incompatible branch. The 10 GB repository cache limit and 7-day eviction policy are shared across all workflows, so aggressive key rotation accelerates eviction while broad prefixes increase stale-hit risk. GitHub does not provide automatic invalidation on dependency resolution changes, and actions/cache@v4 cache versioning does not eliminate this fundamental trade-off.
Two documented approaches exist: (a) embed a version prefix or timestamp in the primary key to force new cache entries on every change, or (b) rely on a broad restore-keys prefix (e.g., deps-) to maximize reuse while accepting occasional stale restores.
Which key strategy minimizes stale restores while maintaining acceptable hit rates for a monorepo with frequent transitive dependency updates? How does the 10 GB repository cache limit influence the choice between aggressive key rotation and broad restore-key prefixes? Can cache versioning in actions/cache@v4 alter this trade-off, or does it only affect cache segmentation?
Use a content‑based primary key that incorporates the lockfile hash and a narrow scope identifier (e.g., the sub‑package path) and keep restore-keys limited to that same scope. Avoid timestamps or run‑specific version prefixes in the primary key.
Embedding a version or timestamp forces a new cache entry on every run, guaranteeing freshness but rapidly exhausting the 10 GB repository quota and lowering overall hit rate. A broad restore-keys prefix (e.g., deps-) maximizes reuse but can pull artifacts from an incompatible branch or older transitive versions, causing stale restores.
actions/cache action matches a cache only when the primary key is an exact string; restore‑keys are evaluated in order and provide a best‑effort partial restore when the primary key is missing.run npm ci (or equivalent) must still execute to ensure correctness.actions/cache@v4 adds an explicit version label to the key namespace; it does not automatically invalidate caches when lockfile contents change.deps-${{ hashFiles('**/package-lock.json') }}-${{ github.workflow }}-${{ github.scope }}, where github.scope is the path or name of the sub‑package being cached.restore-keys as a short, ordered list that mirrors the primary key hierarchy, for example:
restore-keys:
- deps-${{ hashFiles('**/package-lock.json') }}
- deps-restore-keys list to prune overly broad entries that could pull stale artifacts from other branches.Aggressive key rotation creates many distinct cache entries, each consuming space and increasing the chance that the 10 GB quota is reached, which triggers early eviction of older, still‑useful caches. A narrow primary key with a limited set of restore‑keys reduces the number of unique keys, preserving hit rate under the quota constraint.
actions/cache@v4 versioningVersioning changes only the key namespace; it does not provide automatic invalidation on dependency updates. It can be used to segment caches by major version of a toolchain, but it does not eliminate the trade‑off between freshness and hit rate.
Are the caches for each workflow (job) isolated, or do they share the same repository‑wide cache namespace? This determines whether a broad restore-keys prefix could contaminate unrelated jobs.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.