Commit your lockfile, install from it in every environment, and review lockfile changes like code. That way your student-facing app builds the same dependency tree on a laptop, in CI, and in production, and any change shows up as a diff someone can read.
What a lockfile does
npm's documentation says package-lock.json describes "the exact tree that was generated, such that subsequent installs are able to generate identical trees." It is meant to be committed so teammates, deployments, and continuous integration "are guaranteed to install exactly the same dependencies." It also makes dependency changes visible as source control diffs.
Other ecosystems have equivalents, such as Python lock files from your chosen tool, Gradle lockfiles, or Go's go.sum. The principle is the same.
Why this matters for student data
Without a lock, an install might pull a newer release of a transitive package than the one you tested. If that release has a flaw, or new telemetry, you find out in production. In a product that holds student records, "we tested something else" is a poor answer.
The routine
- Commit the lockfile. It belongs in the repository, in the same pull request as any dependency change.
- Install from the lock in CI and deploys. For npm, the clean install command installs from the lockfile and fails if it does not match package.json. Use it in pipelines instead of the plain install.
- Review lockfile diffs. A pull request that changes one line in package.json can change dozens of lockfile entries. Skim the list for packages you do not recognize.
- Update on purpose. Schedule dependency updates in small batches rather than letting them arrive at random.
- Keep a second copy of the evidence. Save the inventory from each release build, so you can answer what shipped in a given version.
Pinning versus ranges
| Approach | Upside | Downside |
|---|---|---|
| Exact versions in the manifest | Very predictable | Updates need manual edits |
| Ranges plus a committed lockfile | Predictable builds, easy upgrades | Needs discipline to update |
| Ranges with no lockfile | Easy to start | Builds can change without a code change |
For most small teams, ranges plus a committed lockfile is the sweet spot.
Pitfalls
- Deleting the lockfile to fix a merge conflict. Regenerate it carefully, then review the diff.
- Different package manager versions producing different lockfiles. Pin the tool version too.
- Treating the lock as a security control. It freezes what you have, including known vulnerabilities. You still need to scan it and update.
Try it yourself
Open the demo and compare the exact versions listed in the inventory. Those are the facts a lockfile pins down.
Click through it at your own pace, or open it full screen.
Safeguard's dependency scanning reads your lockfiles to find known vulnerabilities, and the free scan lets you try that on one repository.
Quick check
Should the lockfile go in version control?
Yes. npm's documentation says it is intended to be committed for exactly that reason.
Does pinning make us more secure?
It makes builds repeatable. Security still depends on scanning and updating what is pinned.
Sources
Last reviewed: 19 October 2026.