The minimum-stability setting is the least stable release type Composer is allowed to choose. It defaults to stable. The prefer-stable setting tells Composer to favour stable releases when it can, even if you allowed less stable ones. Both apply only in the root composer.json.
The scale
The schema documentation lists accepted values from least to most stable: dev, alpha, beta, RC and stable. Versions less stable than your setting are ignored during resolution. The docs add a hint: if you rely on a dev package, specify that in your file to avoid surprises.
| Setting | Effect |
|---|---|
| minimum-stability stable | Only stable releases are candidates (default) |
| minimum-stability dev | Any branch or tag can be chosen |
| prefer-stable true | Stable chosen first, unstable only when needed |
| Per package flag such as @dev | Lets one package use a lower stability |
Why this matters for supply chain risk
A dev branch is a moving target. It has no fixed release tag, so what you get depends on the latest commit on that branch when you run update. That is the opposite of a reviewed, tagged version. Setting minimum-stability to dev across the whole project lets any dependency in the tree resolve to a branch head.
If you need one pre-release package, use a stability flag on that package rather than relaxing the whole project.
Steps to keep your project tidy
- Check composer.json for minimum-stability. If it says dev, ask why.
- If you must allow a lower stability, set prefer-stable to true.
- Prefer the stability flag on the single package that needs it.
- After any update, scan composer.lock for versions starting with dev-. Those are branches.
- Add that check to CI.
composer config minimum-stability stable
composer config prefer-stable true
grep -n "dev-" composer.lock
What prefer-stable does not do
It does not stop an unstable version being chosen if satisfying your constraints needs an unstable one and your minimum-stability allows it. The docs say unstable versions are still selected when required and permitted. So the real guard is the minimum, and prefer-stable is a preference.
Try it yourself
Click through it at your own pace, or open it full screen. Look for packages pinned to a branch rather than a release.
Where Safeguard fits
Safeguard's reachability analysis helps separate advisories your code can reach from those it cannot. You can try a free scan on your own lock file.
Quick check
What is the default minimum-stability?
Stable, according to the Composer schema documentation.
Do these settings work in a dependency's composer.json?
No. Both are root only, so a dependency cannot loosen your stability policy.
Sources
Last reviewed: 19 October 2026.