Dependency hygiene: lockfiles, abandoned packages and an update rhythm
Keeping dependencies under control: reproducible builds, choosing packages, supply-chain basics and a calm cadence for updates.
Open the package.json of any app built with an assistant and count the dependencies. Then count how many you chose yourself. The gap is usually large: the assistant installs a package for every task, including ones three lines of code would solve. Each of those packages is someone else’s code running in your build and on your server, updated on someone else’s schedule.
The lockfile goes in the repo
A lockfile pins exact versions of the whole dependency tree, including dependencies of dependencies. Without it, two builds of the same commit can end up with different code.
package-lock.json,pnpm-lock.yaml,poetry.lockand the like are always committed.- CI and production builds install strictly from the lockfile:
npm ci, notnpm install. The first fails on a mismatch; the second quietly “fixes” it. - Lockfile changes in a pull request get read. If the task was “fix a button” and two hundred lockfile lines changed, it’s worth asking why.
Before you add a package
The cheapest dependency is the one you never installed. Before adding one, ask:
- Could the standard library or a few lines of your own code do this?
- Who maintains it? When was the last release, do issues get answers, is there only one maintainer?
- How much does it pull in? A small package with a hundred transitive dependencies isn’t small.
Abandoned packages
A package without a release in years isn’t automatically a problem. Some things are simply finished. The problem is when a vulnerability is found and nobody is left to fix it. Signs: an archived repository, unanswered security reports, incompatibility with newer runtime versions.
Once a quarter, go through your direct dependencies and flag these. For each, decide in advance what you’d replace it with. Replacing on a quiet day is cheaper than replacing on the day the vulnerability is published.
Supply chain: the basics
A supply-chain attack is when malicious code arrives not through your server but through a package you trust.
- Typos and inventions. A package named almost like a popular one. There’s a specific AI risk here: an assistant may suggest a package that doesn’t exist, and someone may register that name precisely to catch such suggestions. Before installing an unfamiliar package, check that it’s real and the one you meant.
- Install scripts.
postinstallruns on developer machines and in CI with their permissions. In CI you can install with--ignore-scriptsand allow scripts only for packages that genuinely need them. - Hijacked maintainer accounts. A new patch release of a popular package can turn out to be malicious. A lockfile, plus no automatic upgrades during production builds, keeps it from reaching you on its own.
An update rhythm
Updating everything once a year guarantees the update becomes a two-week project with breakage in unexpected places. Updating by hand every day guarantees nobody keeps doing it.
A rhythm that works:
- Small updates, batched and regular. A bot like Dependabot or Renovate opens a pull request with minor and patch versions every week or two. Tests pass, you merge.
- Major versions separately, on a plan. One at a time, with the changelog actually read.
- Security fixes right away. But first check whether the vulnerability affects you. Audit reports are noisy, and many findings are in build tooling that never reaches production. Prioritize by whether the vulnerable code actually runs on your server.
Cleaning up
Assistants install packages but rarely remove them. Tools like depcheck or knip find dependencies nothing uses anymore. Each one you remove is one less thing to update and one less thing to trust.
If you want your dependencies in order without the risk of breaking something, SUBXCAT can sort through them and set up updates that run on their own.