Safeguard
Developer Tools•

Should consumers pin or float internal library versions?

Pin internal library versions with a lockfile and update on a schedule, or float within a compatible range. Trade offs and a default for consuming teams.

Safeguard Security Team
3 min read

For most consuming teams, declare a compatible range, commit a lockfile, and update on a regular schedule or through automated pull requests. That gives reproducible builds and a steady stream of fixes. Pure floating without a lockfile makes builds unrepeatable, and hard pinning without updates strands you on old code.

What the terms mean

Pinning fixes an exact version. Floating accepts any version inside a range. A lockfile records the exact versions resolved at install time, so builds repeat even when the declared range is wide.

Semantic versioning is the contract that makes ranges workable. It says patch releases contain only backward compatible bug fixes and minor releases add compatible functionality, so a range that allows patch and minor updates should be safe if the owner follows the rules.

Options compared

ApproachReproducibleGets fixes automaticallyMain risk
Exact pin, no update processYesNoStuck on vulnerable versions
Range plus lockfile, scheduled updatesYesVia update pull requestsUpdate work needs owners
Floating range, no lockfileNoYes, unreviewedSurprise breakage and unreviewed code
Always latestNoYesSame, more severe

A sensible default

  1. Declare a range that allows compatible updates within the current major.
  2. Commit the lockfile and install from it in CI.
  3. Turn on automated update pull requests, grouped by library, so changes are reviewed and tested.
  4. Merge security releases from your internal libraries within the time in the owner's service level.
  5. Plan major upgrades as work items, not as accidents.

Special cases

Zero major versions: the specification says anything may change at any time in 0.y.z, so pin tightly and read release notes. Prereleases should never be used in production services. Critical libraries may warrant an exact pin plus a rapid update path when the owner announces a fix.

What the owner should do to help

Follow semantic versioning honestly, state supported lines in the README, and mark withdrawn versions as deprecated so installers show a warning. The npm documentation says deprecation warns everyone who tries to install the affected versions. For notices, see how to announce a security release.

Check what you actually run

Declared ranges are not what runs. Read the lockfile or an SBOM of the built artifact to learn the version in production. Teams are often surprised by a transitive copy of an old internal library.

Safeguard can help with the inventory side: its SBOM and dependency scanning shows which services pull in a given internal library, and you can run a free scan at gold.safeguard.sh/scan.

Quick check

Is a lockfile enough protection?

It makes builds repeatable, but you still need a process to update. A lockfile on an old version just repeats the old version.

Should internal libraries use caret ranges?

If the owner follows semantic versioning, a range within the current major is reasonable. Review each update before merge.

Sources

  1. Semantic Versioning 2.0.0
  2. npm Docs: npm deprecate

Last reviewed: 19 October 2026.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.