Skip to content
Engineering/dependency-management

Every dependency is a liability

"We evaluate, add, and remove third-party packages to keep our dependency graph small and maintainable."

Why this exists

I have worked on codebases that required 1,400 npm packages just to render a static marketing page. The engineers who built them did not intend to create a mess, but they lacked a mechanism to say no to new packages. Dependencies accumulate silently. They go unmaintained, introduce security vulnerabilities, and turn every framework upgrade into a negotiation with third-party code.

Operational Flow

1

Justify: Before adding any package, answer three questions in the pull request: What does it do? Can we write a local utility to do this in under four hours? Who maintains it, and when was the last commit?

2

Minimize transitives: Choose packages with the fewest transitive dependencies. Run `pnpm why` to see what a package actually pulls into the lockfile.

3

Lockfiles: Always commit your lockfile. Never delete the lockfile to resolve a package resolution issue.

4

Audit: Run `pnpm audit` and `npm outdated` on the first Monday of every quarter. We patch critical vulnerabilities within 48 hours.

5

Deprecation: Replace deprecated packages within 30 days. Add any package that has not seen a release in 18 months to our deprecation watchlist.

6

Pinning: Pin all production application dependencies to exact version numbers. Avoid floating ranges for major updates.

7

Removal: Grep the codebase after removing a package to ensure no imports remain.

What good looks like

  • Instead of importing `date-fns` for a single formatting task, an engineer writes a 12-line helper utility.
  • An engineer patches two critical vulnerabilities found during the quarterly audit before the end of the week.
  • When a feature is deprecated, you remove the supporting third-party package in the same pull request.

What NOT to do

  • Do not import a library because it is popular. Evaluate it like code you have to write and maintain yourself.
  • Do not leave temporary testing libraries in your package manifest after you finish local exploration.
  • Do not ignore security warnings in development tools. Supply chain attacks often target development environments.
  • Do not upgrade a major dependency on a Friday afternoon without a verification plan.

Dependencies cost nothing to install, but they are expensive to maintain. You pay the price in security patches, upgrade friction, and debugging sessions when a minor version changes behavior under the hood. The question is not whether you can add a package. The question is whether you want to maintain it for the lifetime of the project. Sometimes the answer is yes. Libraries like zod, drizzle, and vitest solve complex problems that are inefficient to write ourselves, but we say no to most packages.

The quarterly audit is a hard requirement. Assign it to a rotating engineer and treat security warnings like a check engine light. The 48-hour patch window exists because we have seen vulnerability notices ignored for weeks under the assumption that someone else was fixing them.