Open package.json and count the lines. Now open pnpm-lock.yaml and count those. The second number
is usually somewhere between three hundred and a thousand, and it is the real answer to "how much
code is in my project".
You wrote almost none of it. You are responsible for all of it.
The idea
A A package of code written by someone else that your project installs and runs. Your dependencies have their own dependencies, which is why a handful of packages becomes hundreds. is code you have agreed to run without reading. That is a good trade, because writing your own date library is a worse use of your life. The cost of the trade is that those packages keep changing: bugs get fixed, security holes get found and patched, and occasionally the authors decide to break something on purpose. Updating is how you stay on the version that has the fix. Not updating is a decision too, it just does not feel like one.
4 . 2 . 7 the version number, three parts
| | |
| | +-- PATCH bug and security fixes only
| | 4.2.7 -> 4.2.8 read the diff, ship it
| |
| +-------- MINOR new features, your code still works
| 4.2.7 -> 4.3.0 usually safe, still test
|
+-------------- MAJOR they removed or changed something
4.2.7 -> 5.0.0 read their upgrade guide firstHow it works
That three-part scheme is called semantic versioning, and most of the JavaScript world follows it. It is a promise, not a guarantee. A patch release can still break you.
Security updates are the ones with a deadline. When a vulnerability is found in a package, it gets a
public advisory with an identifier and a severity, and that publication tells attackers exactly what
to look for. npm audit (or pnpm audit) reads your lockfile and lists any advisories affecting what
you have installed. GitHub's Dependabot does the same thing continuously and opens a pull request
with the fix already applied.
Severity is about the package, not about you. A high severity flaw in a build tool that never runs in production is less urgent than a moderate one in the library that parses incoming requests. Read what the advisory actually describes before you panic or before you ignore it.
What to do
- Turn on Dependabot security updates in your GitHub repository settings. It is two clicks and it is the only part of this that happens without you.
- Do patch and minor updates in a batch, on a schedule you can keep. Once a month is plenty for a
small project. Run
pnpm update, then run the app and click through the paths that matter. - Do major upgrades one package at a time, in their own commit. Ask Claude Code to read the upgrade guide for that specific version jump, apply it, and explain each change. Then read the diff yourself. A migration an AI performed and you approved without reading is a change nobody has reviewed.
Where it breaks
Updates break working software. This is the honest tension: the safest version to run is the one you have tested, and the safest version to run is the one with the security fix, and those are different versions. Nobody resolves that for you. What makes it survivable is being able to undo, which means committing before you upgrade and never batching an upgrade with a feature.
Automated tools also over-report. Advisories fire on packages that only run during your build, on transitive dependencies you cannot upgrade directly, and on flaws that need conditions your app never creates. If you treat every alert as an emergency you will stop reading them within a month.
The opposite failure is slower and much worse. A project two years behind cannot take a security patch without also taking six major versions of everything, and at that point the upgrade is a rewrite.