Upgrade Strategy & Cadence
Decide how often, in what order, and with what process you upgrade — the policy that makes upgrades routine, not heroic.
Why
Without a stated policy, upgrades happen when something forces them — a CVE, a blocked feature, an EOL notice — and every one is an emergency. A strategy inverts this: you upgrade on a cadence you control, in an order that minimizes risk (leaf deps before frameworks before runtime), with a process that's rehearsed. The goal is to make upgrades boring. Teams with a written strategy upgrade 10x more often with 1/10 the incidents, because each upgrade is small, reviewed, and expected. The strategy also makes onboarding trivial: a new engineer reads the policy and knows exactly how to upgrade.
When
Write the policy once, then live it. Revisit when the team size doubles or you adopt a new runtime/framework.
How
1. Define cadence: patch = weekly auto, minor = weekly auto, major = quarterly planned 2. Define order: security patches > leaf deps > dev deps > frameworks > runtime (Node/Python) 3. Define gates: every upgrade PR must pass typecheck + unit + e2e + staging smoke 4. Define rollback: every upgrade is deployed behind a flag or with the old version warm for 1h 5. Define ownership: Renovate owns patch/minor, a named "upgrade captain" owns each quarterly major 6. Document in UPGRADING.md: the policy, the cadence, the order, the rollback procedure 7. Track an "upgrade debt" metric: count of packages >1 major behind; alert if it grows
Example
# UPGRADING.md (lives in repo root) ## Cadence - patch/minor: Renovate, weekly, auto-merge on green CI - major: quarterly, owned by upgrade captain, manual review ## Order (lowest risk first) 1. security patches (immediate, bypass cadence) 2. leaf deps (lodash, date-fns) — low blast radius 3. dev deps (eslint, prettier) — never in prod 4. frameworks (React, Express) — high blast, needs staging 5. runtime (Node, Python) — highest blast, needs infra change ## Gates typecheck && unit && e2e && staging-smoke ## Rollback Every major deploys with the previous image tagged :prev; kubectl rollout undo reverts in <30s for 1h after deploy. ## Debt metric npm outdated --json | jq '[.[] | select(.current < .wanted)] | length' Alert in Grafana if > 5 packages are >1 major behind.
Common Problems
- ⚠No written policy — every engineer upgrades differently, and the team can't tell if a skipped upgrade is intentional or forgotten.
- ⚠Upgrading runtime (Node) and framework (React) in the same PR — when it breaks you can't isolate which caused it.
- ⚠No debt metric — upgrades feel fine until you run npm outdated and discover 40 packages are 2 majors behind.
Best Practices
- ✓Write UPGRADING.md and link it from the README — the policy is only useful if engineers can find and follow it.
- ✓Track an upgrade-debt metric (packages >1 major behind) on a dashboard; a growing line forces the conversation.
- ✓Rotate the "upgrade captain" quarterly so the knowledge of how to do a major upgrade is shared, not siloed.