Upgrade the shared internal library first, release it in a form consumers can adopt without changing at the same moment, then give each consuming team a dated window to follow. Without that order, every team upgrades the same dependency in a different way, or blocks on someone else's library.
Why shared libraries change the plan
An internal library that many services use is a dependency of dependencies. If it pins an old version of a third-party package, every consumer inherits the pin. Teams then cannot upgrade, even though the work is theirs on paper.
The diamond dependency problem described in Google's chapter on dependency management is the general form: two libraries need incompatible versions of a third. The chapter notes that when this happens, the easy answer is to move versions forward or backward until something compatible exists, and that other fixes get costly. Internal libraries make this more common, because one team's release schedule gates another's.
The sequence
- Map the graph. List which services consume which internal libraries, and which third-party versions each library pins. An SBOM per service helps here.
- Pick the leaf first. Start with libraries that have no internal dependencies of their own. Work upward.
- Release the library compatibly. Support the old and new versions of the third-party package for a defined overlap if you can, or publish a new minor version that consumers can take on their own schedule.
- Announce a train with dates. For example, library release in week two, consumer adoption windows in weeks three to eight.
- Track adoption. A simple table of service, library version and status is enough.
- Retire the old version. After the window, stop supporting the previous release and say so.
Roles that keep it moving
| Role | Job |
|---|---|
| Library owner | Ships the compatible release, writes the migration note, answers questions |
| Consuming team lead | Schedules adoption inside the window |
| Manager or program owner | Tracks the table, escalates teams who miss the window |
The migration note matters more than most teams think. A short page that lists what changed, how to adopt, and who to ask removes most of the friction.
Avoid these traps
- Big-bang releases. Forcing every consumer to move on the same day creates one painful week and a lot of rollbacks.
- Hidden pins. A library that quietly pins old versions blocks others. Make pins visible in review.
- No end date. Supporting two versions forever doubles maintenance. Set the retirement date at announcement.
- Owner churn. Name a team, not a person, as library owner.
For a related case in a frontend repository, see upgrade order in a frontend monorepo. For organisations with many languages, who owns dependency upgrades when every service uses a different language covers ownership.
Try it yourself
Click through it at your own pace, or open it full screen. Look at how one component appears across several projects, which is the map you need in step 1.
Where Safeguard fits
Safeguard's SBOM and dependency scanning shows which services use a given package version, so you can build the consumer table without surveying every team. A free scan is at gold.safeguard.sh/scan.
Quick check
Should the library owner upgrade all consumers?
Usually not. The owner ships a compatible release and a migration note. Each consuming team adopts it within a dated window.
How long should the overlap period be?
Long enough for every team to schedule the work, often one to two quarters. Write the retirement date into the announcement.
Sources
Last reviewed: 19 October 2026.