The Hidden Dangers of Automated Dependency Resolution

Note: The core content was generated by an LLM, with human fact-checking and structural refinement.
The assertion that package managers (PMs) are “evil”—a term used partially hyperbolically to make a point—challenges the reliance on these automated tools in modern programming. This perspective argues that while PMs provide undeniable convenience, they introduce profound liabilities by automating processes that should instead demand careful thought and manual oversight.
Core Argument: Automation of Dependency Hell
The primary criticism leveled against package managers is that they facilitate the automation of dependency hell. A package manager’s function is to download packages from repositories, handle dependencies, and then recursively download those dependencies and their subsequent dependencies.
Dependency hell is a real problem in large projects, where a codebase can accrue thousands, or even tens of thousands, of dependencies. When this occurs, developers often lack knowledge regarding how these dependencies work, where the bugs lie, or how the dependencies are being managed.
The issue is not the existence of dependency hell, but the fact that PMs make entering this state far too easy and fast, thereby discouraging careful decision-making.
“All you need to do is lightly tap the command line — for example,
npm installorgo get— and you instantly find yourself in a complex dependency hell.”
The unnecessary automation provided by package managers removes the crucial friction that forces developers to reflect on their choices. When a developer must manually download and integrate a library, they are forced to consider, “maybe I don’t want this” or “maybe I can do this instead”. Manual updates also force developers to be very careful.
1 | # Automated process (too easy, removes friction) |
Distinctions (Not the Problem)
It is important to distinguish the specific target of this criticism. The critique is solely aimed at the package manager itself, which handles automated dependency resolution, and not the following separate concepts:
- Packages: Units of code organization. The Odin language, for example, has packages built in.
- Package Repositories: Places for discovering and storing packages, often functioning like search engines.
- Build Systems: Tools usually specific to a language used for compiling and linking code. For a language like Odin, the need for a separate build system is minimized, with most projects building using
odin build .because linking information is defined in the source code using theforeignsystem.
1 | // Example of a minimal build process that relies on source-defined linking |
Liabilities of Dependencies
Every dependency introduced into a project is a potential liability. In life, having a dependency means being responsible for it; if a dependent entity does something wrong, the responsible party might face consequences. Package dependencies are not dissimilar.
This liability is twofold:
- Security Risks: There are serious problems associated with security risks, especially when developers blindly trust things randomly depended upon from the internet.
- Bug Liabilities: Beyond security, dependencies carry liability for bugs. One team found a “huge amount of bugs” in the widely used SDL2 library, leading them to consider rewriting their window and input handling systems from scratch. The advantage of writing one’s own code is that “it is our code and we can depend on it and correct it when things go wrong”. The author is not advocating writing everything from scratch, but acknowledging that all dependencies are a burden and a liability.
Problems Caused by PMs
Package managers are generally viewed as a net-negative for the programming landscape and should be avoided if possible. They enable people to put themselves and others into “hell”.
A significant issue arises in languages where the concept of a package is ill-defined within the language itself. Consequently, the package manager attempts to define what a package is, leading to various issues. JavaScript, for example, has multiple package managers (like npm), and because each defines the concept of a package differently, it resulted in the need for a package manager manager. This monstrosity arises when competing package managers have different definitions of a package.
Furthermore, automated systems like generic package managers hide the complexity and complications within a project, which are better left visible.
Cultural and Societal Issues
The rapid adoption of PMs coincided with an explosion of new engineers who entered the industry when these tools were prevalent. The reliance on package managers is tied to several deeply rooted cultural and sociological problems:
Unbacked High Trust
Programmers frequently fail to vet their code, especially third-party dependencies, operating on the assumption that random code downloaded off the internet “works”. This is seen as a societal issue: programmers often come from generally high-trust, highly developed countries and apply that societal trust model to the online world. This high-trust environment means that a single person doing something malicious—or even implementing a funny bug—in a widely depended-upon piece of code can “screw everything up” for millions of users.
Gell-Mann Amnesia Effect
This effect describes the tendency to recognize errors or misinformation in articles about subjects one knows well (e.g., horse riding), but then assume that articles about unfamiliar subjects (e.g., JavaScript) are entirely correct, forgetting the general unreliability of the source.
In programming, this manifests when engineers who critique the inability of their own colleagues to program simultaneously choose to “trust every open source package I’ve downloaded”. They hold “unrealistic, excessive trust” in code written by “open source gods,” who may be no more competent than their skeptical colleagues.
Evolutionary Selection Pressure
Programming is a very young industry, roughly 70–75 years old at best. This is not old enough to have established much “good evolutionary selection pressure” or true wisdom. Unlike actual engineering or modern science (which has been around for half a millennium), the industry has not evolved quickly enough to effectively shed bad practices. The few known laws, such as Conway’s Law (the structure of code reflects the company that programs it), stand out because the industry lacks robust, time-tested wisdom.
Mitigation Alternatives
If avoiding package managers entirely is the goal, the recommended approach is manual dependency management.
This involves copying and vendoring each package manually and fixing the specific versions down. This ensures stability, reliability, and maintainability, contrasting with automated systems that hide complexity.
Go’s Paradox and Mitigation Strategies
Some languages, notably Go, manage to avoid the dependency trap longer due to having a built-in package manager but possessing a really good core/standard library (“batteries included”). This strong standard library allows developers to accomplish many tasks, such as building a web server, without needing third-party libraries. Go’s comprehensive standard library reduces reliance on external, small utility packages.
For developers who use automated tools like Go Modules (go mod), several mitigation strategies are suggested to temper the dangers of automation:
- Prioritize the Standard Library: Before seeking an external dependency, developers should always ask if the standard library (std library) already offers a solution.
- Treat
go getas an Architectural Decision: Introducing a new dependency should involve due diligence, including checking its code quality, community activity, issue list, and maintenance status. - Regularly Audit the Dependency Tree: Tools like
go mod graphorgo list -m allshould be used to review what the project actually depends on, and unnecessary dependencies should be cleaned out. - Embrace Copying: Adhering to the principle that “A little copying is better than a little dependency” can prevent unnecessary external links.
The ultimate message is that the best package manager might be the one used the least.
Links to Referenced Articles
Below are the direct links provided in the source material for the content discussed:
- Excerpt from the Odin FAQ on managing code without a package manager:
https://odin-lang.org/docs/faq/#how-do-i-manage-my-code-without-a-package-manager - Tony Bai article on the topic:
https://tonybai.com/2025/09/13/package-managers-are-evil
More
Recent Articles:
- Go Error Handling Evolution and AsA Proposals on Medium on Website
- Go Pointers: Best Practices and the New Initialization Proposal on Medium on Website
Random Article:
More Series Articles about You Should Know In Golang:
https://wesley-wei.medium.com/list/you-should-know-in-golang-e9491363cd9a
And I’m Wesley, delighted to share knowledge from the world of programming.
Don’t forget to follow me for more informative content, or feel free to share this with others who may also find it beneficial. It would be a great help to me.
Give me some free applauds, highlights, or replies, and I’ll pay attention to those reactions, which will determine whether I continue to post this type of article.
See you in the next article. 👋
中文文章: https://programmerscareer.com/zh-cn/pm-is-evil-25/
Author: Medium,LinkedIn,Twitter
Note: Originally written at https://programmerscareer.com/pm-is-evil-25/ at 2025-09-21 11:15.
Copyright: BY-NC-ND 3.0
Comments