A dependable CI cache is a convenience layer, not a source of truth. Design it so that an absent, stale, or unsuitable entry merely causes dependency recovery rather than an incorrect build.
Start with the storage decision
| Material | Preferred mechanism | Reasoning |
|---|---|---|
| Downloaded packages and other reproducible dependency inputs | Dependency cache | GitHub describes caches as reusable files that can be restored for later workflow work. |
| Binary, report, log, or other result produced by a job | Artifact | Artifacts are intended to retain job results and to make files available to other jobs. |
| Credentials, tokens, or session material | Neither | Do not place sensitive values in a cache path or artifact unless a separately reviewed transfer design explicitly requires it. |
On GitHub-hosted infrastructure, each job starts from a fresh runner environment, so dependencies must be fetched again unless reusable files are restored.
Use a cache only for material that the workflow can download or recreate. Treat artifacts as the handoff for deliverables that another job must consume; a cache should not become an implicit release channel.
Construct a narrow cache identity
An explicit cache step needs a path together with an identity key. That key may be assembled from fixed text, workflow contexts, variables, and functions; its size limit is 512 characters.
For dependency material, begin with a namespace and then add every compatibility boundary that matters: operating system, runtime family, architecture, package-manager version where relevant, and a dependency-manifest digest. This is an architecture recommendation, not a vendor-required template.
deps | os | runtime | architecture | manager | lockfile-digestA lockfile digest is useful because changing the resolved dependency set produces a new identity. Including the operating system separately prevents an operating-system change from silently reusing the same cache identity.
Treat invalidation candidates as project-specific questions, not established compatibility effects. Illustrative, unverified questions include whether a runtime upgrade, a native compiler change, or a package-manager migration changes this repository’s reusable directory. Add a dimension only after evaluating it through the project’s clean installation path.
Use fallback matching as a recovery path
Cache lookup considers an exact key with its version metadata before trying prefix matches and then the supplied restore-key sequence. If the current branch yields no eligible entry, GitHub can repeat the search against the default branch, within the applicable cache-scope rules.
Restore keys are evaluated in the listed order. Put the closest compatible fallback first and any broad prefix later, or omit broad fallback entirely when partial dependency reuse could be unsafe.
For example, a team might try a key tied to its lockfile first, then a key covering the current runtime line, and finally no fallback. That ordering is a proposed policy: it is suitable only when the package installation command can reconcile restored contents safely.
Cache version information incorporates the selected paths and compression tooling, allowing GitHub to identify an entry that the workflow can unpack.
Keep untrusted inputs away from privileged work
Cache visibility follows the branch or tag context of a run rather than a particular job or workflow name. A workflow that is allowed to read an entry receives the cached contents without transformation.
Never include credentials, tokens, or secrets in cached directories. GitHub warns that people who can access relevant caches, including certain fork pull-request contexts, may be able to read their contents.
GitHub also cautions that a poisoned cache may lead to code execution when it is later used by a trusted workflow. A safer architecture separates lower-trust pull-request activity from privileged publishing or deployment work, validates regenerated dependencies through the normal installer, and limits cache paths to non-sensitive dependency data. The separation is a design recommendation; its exact event rules require repository-specific review.
Choose the implementation surface
For several supported ecosystems, setup actions can manage dependency caching with less workflow configuration. The documented examples cover package-manager cases such as Node tooling, Python tooling, Java build tools, RubyGems, Go, and NuGet.
Use an explicit cache action when custom directories, a bespoke key layout, controlled fallback prefixes, cross-operating-system settings, or hit-status handling are necessary. That flexibility shifts responsibility for safe paths and compatible key dimensions to the workflow author.
Whichever surface is chosen, keep the recovery command authoritative: on a miss or questionable fallback, it must be able to establish a correct dependency state without trusting cached files as final build output.
Review checklist and boundaries
- Classify every stored path as a recreatable dependency input or a retained job result.
- Document each key dimension and the compatibility risk it addresses.
- Decide whether each restore prefix is safe for the dependency manager in use.
- Exclude secrets and executable or generated material that should not cross trust boundaries.
- Verify behavior for the repository’s pull-request events, branches, and protected workflows before relying on cache reuse.
This guidance makes no prediction about minutes saved, percentage improvement, retention duration, eviction, quota, billing, or cross-platform portability. Those operational details and the complete scope rules need confirmation against current repository settings and documentation.