Why Dependency Reduction Is Still Hard
Including initiatives like e18e, reducing dependencies is a highly valuable practice. I’m a big fan of e18e.
If you remove dependencies, Renovate / Dependabot PRs will decrease.
This reduces the security blast radius and also lowers the burden of investigation and ongoing maintenance.
In addition to improving developer experience, it can also improve production performance.
That said, the path is not easy. The fact that many repositories still rely on jest makes this quite clear.
These challenges are also largely common across other languages.
Common Challenges
Social (Sociotechnical)
We meet again.
As Gerald Weinberg put it, “no matter how it looks at first, it’s always a people problem.”
Dependency reduction is no exception.
Low Interest in Non-Functional Concerns
Most maintainers and code owners are not deeply interested in dependencies or non-functional requirements themselves.
Given limited time, attention naturally gravitates toward feature development.
Lack of Trust in PR Authors
PRs from unfamiliar contributors are often ignored or left unreviewed.
This is even more true in the age of AI. Building trust comes first.
Different Processes Across Repositories
Some repositories accept direct PRs, while others require opening an issue first.
Understanding each repository’s workflow can be burdensome. Even when documented, effective contributions often require reading the “room.”
You Still Need to Release
Especially for poorly maintained repositories, releasing can be more burdensome than making the change itself.
As long as the project is still in use, you cannot simply merge and walk away.
No Real Interest in the Repository Itself
If the last update was years ago, or there are no incentives within an organization, improvements are unlikely to move forward.
Even with AI, Review Is Still Required
If only part of a library is used, it’s possible to rewrite it inline with AI.
This is particularly effective for removing legacy dependencies. However, the review burden still remains significant.
Ambiguous Ownership
In repositories with multiple maintainers, it is often unclear who is responsible for reviewing dependency-related changes, leading to stagnation.
Still Not a Common Practice
Dependency reduction is not yet standard practice.
Its value often needs to be explained each time, which adds cognitive overhead.
Technical
If this were purely a technical problem, it would feel much easier.
Ensuring Compatibility Is Hard
Even when replacing parts of lodash or moving to native APIs, subtle behavioral differences can occur.
If compatibility is not 100%, uncertainty remains, increasing validation costs or causing PRs to be rejected.
Even Minor Upgrades Can Break Things
e18e efforts can significantly reduce dependencies, sometimes just through upgrades.
However, even minor version updates can introduce issues, not only within the library itself but also through interactions.
Insufficient Test Coverage
Tests are often deprioritized.
Without sufficient regression tests, it’s hard to be confident that everything still works.
Benefits Are Hard to Measure
Removing a single dependency may have only a small performance impact.
Moreover, due to transitive dependencies, removing one explicit dependency may not change the final dependency graph.
This is common in performance work: meaningful gains often come only after many small improvements are accumulated. However, improving the entire ecosystem to achieve that is time-consuming.
After the Easy Wins, Only Hard Dependencies Remain
After easy fixes, what remains are complex dependencies.
Fixing A may require changes to B, which in turn affects C and D.
Hard to Understand Impact Scope
Especially in monorepos, it takes time to determine how far the impact of a dependency removal extends.
Even seemingly unrelated scripts can be affected.
Dependencies Come Back
Even after significant effort to reduce them, dependencies can quickly accumulate again.
Recommended Approaches
Remove Completely
If a tool like knip confirms that a dependency can be removed without impact, this is the simplest approach.
It is effectively risk-free.
Make Small, Incremental Changes
Smaller PRs are easier to review and help build trust.
However, this increases the number of reviews and releases required.
Replace with AI-Generated Implementations
A more aggressive approach, but it can often be effective.
Breaking away from legacy constraints and rebuilding from scratch can sometimes be faster.
That said, adoption and community considerations require care.
Prevent Reintroduction
Reducing dependencies is not enough. You also need to prevent them from creeping back in.
Tools like the following can help establish guardrails:
Conclusion
Even when the goal is simply to remove dependencies, the same kinds of challenges found in broader software development inevitably emerge.
A future where AI solves all of this doesn’t seem particularly realistic. And even if it did, whether our electricity bills go down or up is a different question.
P.S. I also built a small tool in this area: