What Is a Lockfile?
A lockfile records the exact version of every dependency - direct and transitive - so the same install produces the same tree every time.
A manifest like package.json says "react ^18". That range can resolve to different versions on different days. A lockfile (package-lock.json, yarn.lock, poetry.lock, Cargo.lock) freezes the resolution so installs are deterministic.
Manifest vs lockfile
The manifest declares what you want, often as version ranges. The lockfile records what you actually got, down to exact versions and checksums. The lockfile is what makes "it built yesterday" reliably build today.
Why CI must use it
In CI, install from the lockfile in frozen mode - npm ci, yarn install --frozen-lockfile, poetry install. This refuses to silently upgrade anything and fails loudly if the lockfile and manifest disagree, catching drift instead of hiding it.
A small example
Running npm install in CI may quietly resolve a new patch release and mutate the lockfile, so two runs differ. Running npm ci instead deletes node_modules and installs strictly from package-lock.json, failing if the lockfile is out of sync.
Lockfiles power cache keys
Because the lockfile changes exactly when dependencies change, its hash is the ideal cache key. Hashing the manifest instead would miss transitive updates and serve a stale cache.
Commit it and review it
Lockfiles belong in version control. Reviewing lockfile diffs in pull requests surfaces unexpected dependency changes - a key signal in supply-chain defense, since a malicious transitive bump shows up as a lockfile change.
Key takeaways
- A lockfile pins exact versions of all dependencies for reproducible installs.
- CI should install from the lockfile in frozen mode, never update it.
- The lockfile hash is the natural cache key for dependencies.