They answer different questions. Dependency locking pins which versions Gradle resolves, so builds are repeatable. Dependency verification checks the checksums or signatures of the files Gradle downloads, so a tampered artifact fails the build. For a mobile CI pipeline, locking prevents surprise upgrades and verification catches swapped files.
What locking does
Gradle's documentation explains the problem with dynamic versions. A declaration such as 5.+ can resolve to different versions over time, so builds can break unexpectedly. To get reproducible builds you lock versions. Gradle writes a gradle.lockfile, and its header says the file is expected to be part of source control. The documentation also notes Gradle will not write lock state to disk if the build fails, so an invalid state is not persisted.
Locking says nothing about whether the bytes behind a locked version are genuine. If a repository serves a modified file for the same version, the lock still passes.
What verification does
Verification records expected hashes in gradle/verification-metadata.xml. The documentation says that when the build downloads an artifact it computes the checksum, and if it does not match, the build fails instead of using the tampered file. It also says checksums verify integrity but not authenticity, while signatures verify authenticity but may use weak hashes, and for the strongest security you use both.
Side by side
| Question | Locking | Verification |
|---|---|---|
| Stops a surprise new version | Yes | No |
| Stops a swapped file at the same version | No | Yes |
| Where it lives | gradle.lockfile | gradle/verification-metadata.xml |
| Change cost | Update on each upgrade | Update on each upgrade |
| Covers plugins | Per configuration | Yes, plugins and libraries |
Why mobile projects feel this more
Android apps pull a large tree of transitive libraries and Gradle plugins from public repositories. A plugin runs code in your build, with access to whatever the job can see, including signing material. That is a good reason to verify plugins as well as libraries. Our post on why dynamic versions are a bad idea in mobile releases covers the first half of the story.
A rollout plan
- Replace dynamic versions with fixed ones where you can.
- Generate lockfiles and commit them. Review the diff when they change.
- Generate verification metadata, bootstrap it carefully, and commit it. Treat the first bootstrap as trusting what you have now, and sanity check anything unfamiliar.
- Make CI fail on mismatch, not warn.
- Assign an owner for upgrades so the files do not rot into a rubber stamp.
- Rebuild from clean in CI regularly so you notice failures early.
Existing posts on bootstrapping verification safely go deeper.
Common trap
Teams update verification metadata automatically on every failure. That defeats the control. A failed check should be a person asking why the file changed.
Try it yourself
Open the demo and see how the dependency inventory lists each component with its version. That list is what locking pins and verification checks.
Click through it at your own pace, or open it full screen.
Where Safeguard fits
Safeguard adds SBOM and dependency scanning plus reachability analysis on top of locked versions, so you can tell which advisories matter. Try the free scan.
Quick check
If I use verification, do I still need locking?
Yes, if you want repeatable versions. Verification alone does not stop a version from changing when a new one is declared or resolved.
Do lockfiles go in version control?
Gradle's documentation says the lock file is expected to be part of source control.
Sources
Last reviewed: 19 October 2026.