Dependency lag is the distance between the version you run and the newest release, measured in versions, in time, or both. To measure it, list every direct and transitive dependency with its current and latest version, record the gap, and trend it per repository. Start with a command your package manager already provides.
Definitions
Lag in versions counts how many releases or major versions you trail. Lag in time is how long ago the newer release shipped. Time is easier to explain to non-engineers: "this library is 14 months behind its latest release" lands better than a version tuple.
Step 1: get the raw numbers
For JavaScript projects, npm outdated prints a table. Its docs define two of the columns: "wanted" is the maximum version that satisfies the semver range in package.json, and "latest" is the version tagged latest in the registry. A large gap between wanted and latest means your declared range is holding you back. A gap between current and wanted means you simply have not run an install.
npm outdated --long
Other ecosystems have equivalents. Use your package manager's outdated or list command, or an inventory from an SBOM.
Step 2: add the transitive layer
Direct dependencies are the minority. Most versions in a typical lockfile belong to packages you never chose. Pulling the full tree from a lockfile or an SBOM shows the gap there too, and it often hides the oldest items.
Step 3: record it as a small table
| Repository | Direct deps behind | Oldest gap | Major versions behind | Notes |
|---|---|---|---|---|
| service-a | count | months | count | one runtime near end of life |
Keep the columns few. If nobody reads a column, drop it.
Step 4: decide what the numbers mean
Lag is a signal, not a verdict. A stable library that has not released in years is not "behind." Look at three things together:
- Is there a known vulnerability in the version you run?
- Is the version still supported by its maintainers?
- Is the gap crossing a major version, where breaking changes live?
Any yes moves the item up. Zero yes means it can wait for the next scheduled batch.
Step 5: trend, do not snapshot
A single snapshot makes people defensive. A monthly trend per repository, shared plainly, makes the work visible. Aim for the line to flatten, then fall.
Common mistakes
- Measuring only direct dependencies and missing the oldest transitive ones.
- Treating every red row as equal.
- Counting a pinned version as safe because it is pinned. Pinning is good for reproducibility, but it is also how lag is created.
- Letting the number become a target, so people bump versions without testing.
Safeguard's SBOM and dependency scanning lists direct and transitive packages with their versions, and reachability analysis shows which outdated or vulnerable ones your code actually calls. Autonomous remediation can open fix pull requests; it is off by default and every category starts on Manual. You can try a free scan at gold.safeguard.sh/scan.
Try it yourself
Click through it at your own pace, or open it full screen. Expand the tree and look for the oldest versions deepest in it.
Quick check
Is lag in time or in versions more useful?
Time is easier to communicate, versions are easier to act on. Track both and report time to leadership.
Does zero lag mean zero risk?
No. The newest version can still contain a flaw, and a brand new release can be malicious. Lag is one input among several.
Sources
Last reviewed: 19 October 2026.