The cost of a dependency you did not choose

A coding agent working in one of the repositories we look after added a date formatting library. It took about four seconds. There was no discussion, because there was nothing to discuss with: the change arrived complete, the tests passed, and the library is a perfectly reasonable one that thousands of teams use.
That package is now in the build. It is in the lockfile, the licence report, the vulnerability scan, the container image, and in the set of things a new engineer has to understand before they can safely change how a date is displayed. It will still be there in five years. The agent will not.
This is the part of AI-assisted development that nobody complains about, which is exactly why it is worth writing down. The complaints are all about code quality. Dependencies are harder to notice, and they last longer than the code that introduced them.
Here is the problem, in three costs and one fix.
1. The small effort that used to protect you is gone
Adding a package by hand was never hard. It was, however, embarrassing.
You had to search for it, read the readme, decide the name was right, type it, and then, at some point, mention it in the pull request description where a colleague might ask why. That whole sequence took a few minutes and carried a small social cost. The cost was useful. It stopped the additions that were convenient rather than necessary, because convenience is not a good enough answer when someone might ask you out loud.
An agent has no such hesitation. It has read a large amount of code in which the standard solution to a given problem is a particular package, so it uses that package as automatically as a human writes a for loop. The choice is usually defensible. The problem is that it was never presented as a choice.
We now assume that any repository where agents write code will collect dependencies faster than the same team would have accumulated them by hand, and we plan for that rather than being annoyed by it. The planning is the whole fix.
2. What a dependency actually costs, over five years
The install is free. Everything after it is not.
The upgrade cost. With every package, you have to follow somebody else's release schedule. They release a major version, they deprecate a function you rely on, they change a default. None of these events are your decision and all of them happen on their schedule. Ten packages, each demanding attention twice a year, is a recurring quarter of somebody's week that appears nowhere in any plan.
The security risk. A package deep in the dependency tree runs with exactly the same permissions as the code you wrote yourself. Nobody read it. Nobody is going to read it. Your scanner will tell you about known vulnerabilities in it, which is genuinely useful and covers only the ones that have been found and published.
The compliance risk. In any regulated environment, every dependency is something an auditor can ask about: what licence, what data does it touch, where does it send telemetry. A package added without discussion during a two-week work cycle becomes a question in a diligence process eighteen months later, and the person answering it will not be the person who added it. If the product handles regulated data, the argument in compliance is a specification problem applies here directly: the obligation exists whether or not anyone wrote it down.
The cost of removing it. This is the one people underestimate most. Removing a dependency is almost always harder than adding one, because within about two weeks its API has spread into your own code. Once imported, a library shapes your code: your code now follows the library's approach to the problem.
3. The usual problem is duplication
Agents rarely pick a bad package. They pick the popular one, which is usually the right choice.
What they cannot do is know what is already in your build. Ask for date handling in one change and a validation helper in another, and you can easily end up with two libraries that overlap by seventy percent, each added by a different reasonable decision made a month apart. Neither is wrong. Together they are a maintenance problem and a source of confusion for the next engineer, who now has to learn an unwritten rule about which one is used where.
We have seen the same thing with HTTP clients, with schema validators, and most often with large utility libraries, where a package with two hundred functions gets added so that one of them can be used once.
Transitive dependencies make this harder to see. One direct addition can bring in dozens of packages nobody named. Your manifest gained one line. Your build gained dozens of packages.
The fix: make the team review the dependency list
The fix is simple and it works. Stop treating the manifest and the lockfile as build output. Treat them as design decisions that happen to be stored in a file.
Compare the dependency list on every change. Not as a report someone reads later. As a check in continuous integration that fails when a new top-level entry appears without an explanation. This is the same principle as running evals in the pipeline, described in evals in CI for coding agents: the check has to block the change, or it has no effect.
Require one sentence. Why does this exist, and what does it replace. That is the whole requirement. If nobody can write the sentence, the package should not be in the build. It takes about ninety seconds and it catches the duplicates immediately, because writing "we need a date library" while a date library is already installed is the moment the problem becomes visible.
Review transitive additions separately. They arrived without anyone choosing them, so they need the one place in the process where a human looks at the whole dependency tree rather than the single line.
Keep the package behind your own thin layer where the cost of removing it matters. One file that wraps it, and the rest of your code calls your file. Then replacing it later is a day rather than a quarter. This is the small version of the argument in avoiding vendor lock-in, and the deciding question is the same: how expensive is it to stop using it.
When adding the dependency is clearly right
None of this is an argument for writing everything yourself. That mistake is more expensive and more common than people think.
If the problem is hard, well specified, and already solved under real scrutiny by people who specialise in it, take the package. Cryptography, timezone arithmetic, PDF parsing, protocol implementations, anything where a subtle error has consequences and where the failure gives no warning. Writing your own crypto to avoid upgrade work is a bad choice in every way.
The case that is hard to decide is the small utility: a package you could reimplement in under a day, solving ten problems when you have one. There, thirty lines you own are better than a dependency you must track, upgrade, audit, and eventually replace.
Why this gets worse before it gets better
The 2025 DORA report, based on responses from nearly 5,000 technology professionals, found that AI adoption relates positively to delivery throughput and negatively to delivery stability, and summarised the underlying dynamic as "AI doesn't fix a team; it amplifies what's already there". Dependency management is a good example of exactly that. A team that already reviewed its manifest carefully will keep doing so at higher volume. A team that never looked will now add unreviewed packages several times faster.
There is a security side too. Veracode's Spring 2026 research across more than 150 models found generated code compiling and running correctly over 95 percent of the time while passing security checks in roughly 55 percent of generations. That study is about the code itself, and the same reasoning applies to what the code brings in: correctness is checked constantly, and the choices around it are checked rarely.
Thanks to the teams who let us read their manifests and count what nobody remembered choosing. In every case the packages were fine individually. What nobody could explain was why there were three of them doing the same job.
Code gets rewritten. Dependencies stay, and the next team takes them over.
Related guide: Maintaining custom software.
Sources
- 2025 DORA report announcement, Google Cloud: nearly 5,000 respondents; AI adoption relates positively to throughput and negatively to delivery stability, and amplifies a team's existing practices.
- Veracode, Spring 2026 GenAI Code Security update: across more than 150 models, over 95 percent of generations compiled and ran correctly while roughly 55 percent passed security checks.


