Use composer install in production. With a committed composer.lock it installs the exact versions recorded there. Composer update resolves the latest versions allowed by composer.json and rewrites the lock file, so run it deliberately on a development branch, review the diff, and deploy only what was reviewed.
What each command does
According to the Composer documentation:
| Command | With a lock file | Without a lock file |
|---|---|---|
| install | Uses the exact versions listed | Resolves dependencies, installs them, and creates a lock file |
| update | Fetches latest allowed versions and rewrites the lock file | Same, and creates one |
After you pull changes from version control, the docs recommend running install to sync the vendor directory with the lock file.
Why production should not run update
A production deploy that runs update picks whatever is newest inside your version ranges on that day. That includes a release published an hour ago, which nobody on your team has seen. The code you tested is no longer the code you ship.
The same reasoning applies to supply chain risk. If a dependency is compromised and a new version is published, an update on deploy pulls it in without a review step.
The warning you should not ignore
Composer displays a warning during install if composer.lock has not been updated since the last change to composer.json. It means your manifest and lock file disagree. Fix it by running update for the changed package on a branch and committing the result, not by silencing it.
The docs mention an option that overwrites the lock file hash to suppress that warning without updating package versions. Use that only when you have confirmed the lock file is correct.
Production flags
The docs describe a no-dev option on install that skips require-dev packages and the autoload-dev rules. Use it on production builds so test tools are not deployed.
composer install --no-dev
A safe update workflow
- Create a branch.
- Run update for the specific package, or for all if you mean to.
- Run your tests and composer audit with the locked option.
- Review the composer.lock diff.
- Merge, then deploy with install.
Version constraints matter too
The Composer versions guide describes the caret operator as allowing non-breaking updates, so a caret on 1.2.3 means at least 1.2.3 and below 2.0.0. It also warns to be careful with unbounded ranges. Wide ranges widen what update can pull in.
Quick check
Should I commit composer.lock?
For an application, yes, per the Composer docs. For a library, it is not necessary.
Does install ever change composer.lock?
If a lock file exists, install uses its exact versions. If none exists, Composer creates one after resolving.
Safeguard's dependency scanning reads your project files and flags known advisories, and gates on pull requests can stop a vulnerable lock file change before merge. The free scan is a place to start.
Sources
Last reviewed: 19 October 2026.