Skip to content
Back to Maintenance & LTS

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.