Make the cache key include a hash of the lockfiles that define your dependencies: the Gradle lockfile, Podfile.lock or Package.resolved. When a dependency changes, the key changes and CI downloads fresh. Be careful with fallback restore keys, because they can bring back older content on purpose.
How cache matching works
The documentation for a hosted CI cache describes the order. It first looks for an exact match to the key. If none exists, it looks for partial matches of the key. If there is still no match and you provided restore keys, those are checked in order for partial matches. On a miss, a new cache is saved when the job succeeds. If nothing matches in the current branch, the search repeats on the default branch, subject to scope restrictions.
That chain is why the key design matters.
What to put in the key
| Ecosystem | Lockfile to hash | Why |
|---|---|---|
| Gradle | gradle.lockfile and the wrapper properties | Pins resolved versions, tool version |
| CocoaPods | Podfile.lock | Records the exact version of each pod |
| Swift packages | Package.resolved | Records resolved package versions |
| Ruby build tooling | Gemfile.lock | Pins the automation gems |
Add the operating system and the toolchain version, such as the Xcode or JDK version, so a cache built for one is not restored into another.
CocoaPods' own guide says the Podfile and Podfile.lock should always be under version control, and that CocoaPods honours the version in Podfile.lock unless the dependency is updated or an update is run. Gradle's dependency locking documentation similarly says the lock file is expected to be part of source control. A key built from these files tracks real dependency state.
The restore key trade off
A restore key with just a prefix gives a partial hit: an older cache is restored, and Gradle or the pod tool fills the gap. That is faster, and it is fine for downloaded public artifacts that the tool re-verifies. It is risky if the cached content is trusted without verification, for example build outputs. Rules of thumb:
- Use exact keys for anything the build trusts blindly.
- Allow prefix fallback only for download caches.
- Never fall back across a trust boundary, such as from a pull request cache into a release job.
- Include a manual version number in the key so you can invalidate everything in one edit.
Rotate on advisories
When a compromised package version is announced, bump the manual version in the key. The cache is then rebuilt from lockfiles, and any poisoned download is gone. Our post on purging CI caches after a compromise goes through that.
A short test
Change one dependency version in a branch and confirm the job logs a cache miss and downloads the new version. Then revert and confirm the old key hits. If a change does not produce a miss, the key is missing an input.
Try it yourself
Open the demo and look at how the inventory changes as dependencies change. That is the signal your key should track.
Click through it at your own pace, or open it full screen.
Where Safeguard fits
Safeguard produces an SBOM and scans the dependencies named in your lockfiles, then applies policy. A free scan is the quickest start.
Quick check
Should the key include the branch name?
Often yes for build outputs, so branches do not trample each other. For download caches, lockfile hash alone is usually enough.
Do restore keys weaken security?
They can, if the restored content is trusted without checks. Use them only where the tool re-verifies what it downloads.
Sources
Last reviewed: 19 October 2026.