Each new service gets its own build file, and each team picks versions on its own, often copying from the monolith or from a recent project. The result is one library in several versions, and a vulnerability fix that must be applied in every place instead of once.
How duplication happens
In a monolith, one build usually resolved one version of each library. Split the system into services and you create many resolution points. Each team copies a starting template, adds a feature, and pins whatever version works that week. A shared parent file that used to enforce versions may not come along.
Transitive dependencies make it worse. Maven's documentation gives a clear example in the dependency convergence rule: two dependencies can each pull in the same artifact at different versions, and the difference is not obvious from the declared dependencies alone.
Why it matters for security
When an advisory lands, you need to answer "which services use the affected version?" Duplication multiplies the answer. It also hides drift. One service gets the fix, three do not, and the dashboard shows the finding as open without telling you where.
How to converge, step by step
- Build a cross service inventory. Gather resolved dependencies from every service into one list, keyed by package name and version.
- Rank by spread. Libraries present in many versions come first, especially those with known vulnerabilities.
- Pick a target version per library. Choose the newest version that all services can adopt with limited changes, and note the exceptions.
- Centralize version control. In Maven, a bill of materials or dependencyManagement can pin one version across modules, and the enforcer plugin's dependencyConvergence rule can fail a build when versions diverge. Other ecosystems have similar mechanisms, such as lockfiles or constraints.
- Enforce in CI. Fail or warn when a service introduces a version outside the approved range.
- Review quarterly. Drift returns unless you check.
What to centralize and what to leave alone
| Centralize | Leave to the team |
|---|---|
| Logging, serialization, HTTP clients, crypto | Test only libraries |
| Anything with a recent advisory | Libraries used by one service only |
| Framework versions | Small utilities with no network exposure |
Do not force everything into one shared file. Too much central control slows teams and invites exceptions. Aim for the libraries that carry the most risk.
A warning about shared libraries
A shared internal library can also spread a vulnerable version to every service that consumes it. We cover that in a separate post on common libraries in a monolith split. For now, remember that the fix is the same, which is knowing where each version lives.
Safeguard's SBOM and dependency scanning can build the cross service inventory, and its policies can warn or block when a pull request adds a version outside your approved range. Fix pull requests are available but off by default, with every category on Manual until you change that. See SBOM for microservices architecture for the inventory side.
Quick check
Is one version everywhere always the goal?
No. Aim for few versions of risky libraries and a clear owner for each exception.
Does a lockfile fix duplication?
A lockfile makes each build repeatable. It does not make different services agree, so you still need a shared target version.
Sources
Last reviewed: 19 October 2026.