Small npm Packages Are Mostly Dead
Why AI-generated code replaces the need for small npm packages, and where the line is between a dependency you still need and one an LLM can write on th...
I stopped installing most small npm packages.
Not because of the supply chain attacks, though those are a real concern. Not because of bundle size, though that matters too. I stopped because AI can write the same utility function in seconds, tailored to my exact codebase, with zero ongoing maintenance cost.
The calculus changed. Most of us haven't updated our mental model to match.
The Threshold Thesis
Packages under roughly 500 lines of single-purpose code are the target here. The kind of package you install because writing a slugify function feels like reinventing the wheel, or because lodash.get saves you three lines of optional chaining. These packages exist because copying code was manual and error-prone, and shared libraries solved a real coordination problem.
AI changes that problem entirely.
A utility function that 500 people use across 500 projects looks identical in every project. A utility function that AI generates from scratch per project looks slightly different every time, but it's perfectly adapted to each codebase's conventions, style, and type system. It doesn't need to be abstracted for every possible use case. It just needs to work in your one project.
The 500-line threshold is not arbitrary. It's roughly the point where edge case handling, configuration surface, and cross-platform concerns start to outweigh the one-off generation cost. Below that line, AI wins almost every time.
The Left-Pad Paradox, Revisited
The infamous left-pad incident of 2016 broke the internet over an 11-line package. Eleven lines. npm unpublishing that package cascaded through thousands of downstream builds because the entire ecosystem assumed it would always be there.
In 2026, an AI agent generates left-pad in its sleep. It writes it, tests it, and moves on. The concept of depending on an 11-line shared library for string padding makes no sense when the code can be regenerated on demand, zero risk, zero external dependency.
The npm ecosystem was built to solve a coordination problem that AI has largely eliminated at the small-package scale. AI does not need a package registry for anything it can produce in a single generation pass.
The Real Cost of Packages
When you install a small npm package, you are not just getting the code. You are signing up for:
Supply chain risk. Every dependency is an attack surface. The Twelve-Factor App methodology says to declare dependencies explicitly for good reason. left-pad, event-stream, colors.js, faker.js. Each one demonstrated that the npm ecosystem's trust model assumes goodwill. AI-generated code assumes nothing. It does not have a maintainer who can go rogue, lose interest, or accept a malicious PR.
Maintenance burden. Renovate bots create PRs for every transitive dependency bump. You review, approve, merge, repeat. Each package you remove eliminates a recurring time tax. AI-generated code has no versioning. It does not need upgrades unless your requirements change.
Breaking changes. Semver is a good-faith agreement, and it breaks constantly. A package that worked fine on Tuesday breaks your build on Wednesday because a minor version bumped a behavior you relied on. AI-generated code ships once, works as intended, and never changes unless you regenerate it.
Bundle size. Even tree-shaken packages carry overhead. The import itself, the module resolution, the edge cases the package handles that your code never hits. AI generates exactly what you need and nothing else.
Where AI-Generated Code Falls Short
I'm not arguing that all packages are obsolete. The counterarguments are real and worth taking seriously.
Edge cases are the obvious one. A date formatting library handles timezones, i18n, calendar systems, and historical timezone changes. AI can generate a decent date formatter, but it will miss edge cases that a library like date-fns has spent years discovering and fixing. The question is whether your project needs those edge cases.
Community knowledge matters. Stack Overflow answers reference real packages. When someone posts a bug report with lodash.get in the title, everyone knows exactly what they mean. AI-generated code is unique per project, which means bug reproduction becomes harder and debugging requires reading unfamiliar generated code on every project.
Audit trails are real. npm audit is imperfect but understood. There is no equivalent for AI-generated code. No vulnerability database, no CVE tracking, no way to know whether the generated slugify function has a ReDoS vulnerability that the community-discovered version fixed two years ago.
Team consistency is the hardest problem. If everyone on a team AI-generates a date picker, you get N slightly different implementations. Some will handle leap years correctly, some won't. Some will use Intl.DateTimeFormat, some will hand-roll locale support. The consistency that a shared package provides is not just about code reuse. It's about shared behavior across the team.
The New Dependency
There is an irony here that is worth naming. Replacing npm packages with AI-generated code means trading one dependency for another. Instead of depending on npm, you depend on OpenAI, Anthropic, or whoever provides your AI tooling. I wrote about this in Everything Is Markdown Now — if your workflows are built on model-specific APIs, you have a dependency you didn't need.
If your AI provider changes their model and the generated code quality shifts, or if they deprecate an API you rely on, you have the same problem you had with npm, just shifted to a different layer. The difference is that the AI dependency is a single point, not a tree of transitive dependencies. You manage one relationship instead of hundreds. But it is still a relationship.
The practical response is to treat AI-generated code like any other dependency. Review it. Test it. Own it. The AI is a generator, not a guarantee.
Where Packages Still Win
Not everything under 500 lines is a candidate for elimination.
Complex integrations like Auth0, Stripe, and aws-sdk handle protocols, authentication flows, and error recovery that AI is not equipped to reproduce reliably. These are not utilities. They are SDKs that encode the behavior of a moving target external system. Generating an OAuth handshake from scratch every time is not just wasteful, it's dangerous.
Systems where correctness is safety-critical also stay on the package side of the line. Cryptographic libraries, date/time handling for regulated industries, and anything involving financial calculations benefit from the audit trail and battle-testing that shared packages provide.
The line is not purely about line count. It's about whether the problem space is stable, well-understood, and unlikely to surprise you. If it is, AI wins. If it involves external systems, safety guarantees, or edge cases that took a community years to discover, the package still earns its place.
The Real Question
The question I keep coming back to is not whether AI can replace small packages. It clearly can for most cases. The question is whether the team cost of slightly different implementations outweighs the maintenance cost of shared packages.
For a solo developer or a small team with strong conventions, AI-generated utilities are a clear win. No renovate noise, no supply chain surface, no versioning surprises. For a large team where consistency matters more than individual productivity, shared packages still provide a baseline that AI-generated code cannot replicate without additional tooling.
The answer depends on where you sit. But the default should no longer be "install the package." It should be "can AI write this in one pass?" Most of the time, the answer is yes.
And if the answer is yes, you are better off owning the code than renting it.
Newsletter
A weekly newsletter on React, Next.js, AI-assisted development, and engineering. No spam, unsubscribe any time.