Managing Dependencies: Semver, Updates, and Audits
Why Dependency Management Is Production Work
Most backend incidents are not caused by your code alone. They are caused by dependency changes, transitive vulnerabilities, or breaking updates. Dependency management is part of system reliability.
SemVer Basics
Most Node packages use Semantic Versioning: MAJOR.MINOR.PATCH.
- MAJOR: breaking changes
- MINOR: new features, backwards compatible
- PATCH: bug fixes
Version Ranges in package.json
Common patterns:
^1.2.3allows minor updates (1.x.x)~1.2.3allows patch updates (1.2.x)1.2.3pins exact version
Why Lockfiles Matter
package-lock.json pins the full dependency tree. Without it, two developers can install different versions and get different behavior.
Deterministic Installs with npm ci
npm ci
Use npm ci in CI/CD to reproduce the exact locked dependency tree.
Transitive Dependencies
You may not import a package directly, but your dependencies do. A vulnerability can appear deep in the tree.
Auditing
npm audit
Audit checks known vulnerabilities in your dependency graph.
Update Strategy
- Patch updates: usually safe, still test
- Minor updates: schedule, test in staging
- Major updates: treat as a project, plan migration
Production Rule: Update with a Process
Do not “randomly update packages” on a production backend. Have a workflow:
- Update in a branch
- Run tests
- Deploy to staging
- Monitor
- Promote to production
Reducing Dependency Risk
- Keep dependency count low
- Avoid heavy libraries for small tasks
- Prefer well-maintained packages
- Be cautious with abandoned packages
Pinning Node Version
Dependencies behave differently across Node versions. Pin Node in production and keep it aligned with your CI.
JS Note
Dependency behavior is runtime behavior. TypeScript does not protect you from runtime breaking changes in dependencies.
Next Step
Next we will discuss monorepos: when they help, when they hurt, and what “good structure” looks like for growing codebases.