A lockfile is a file generated by a package manager that records the exact version of every dependency a project actually resolved to, including the transitive dependencies pulled in indirectly. Familiar examples are Gemfile.lock (Ruby), package-lock.json (npm), composer.lock (PHP), poetry.lock (Python), and Cargo.lock (Rust). It sits alongside a human-edited manifest that expresses requirements in looser terms.
The point of a lockfile is reproducibility. Cargo’s documentation explains that without pinning, “different developers building the same package at different times could get different versions”; the lockfile captures the exact revision so that “others build the project using this exact” version. npm’s documentation makes the same case, saying package-lock.json “describes the exact tree that was generated, such that subsequent installs are able to generate identical trees, regardless of intermediate dependency updates.”
The division of labor is the same across ecosystems: a manifest such as package.json, composer.json, or Cargo.toml says what you want in flexible terms, and the lockfile records what you got in exact terms. Composer’s documentation describes this directly, noting that the lock file locks “the project to those specific versions” so that everyone installs the exact same dependencies.
Lockfiles matter because they turn dependency installation from something that quietly drifts over time into something deterministic. Teams commit the lockfile to version control so that a teammate’s machine, a continuous integration server, and a production deployment all install byte-for-byte the same dependency set, which is essential for reliable and reproducible builds.