Back to System Design
System Design
easy
mid

How would you design a release strategy for a JavaScript library using semver and changesets?

Semver strictly: breaking → major, additive → minor, fixes → patch. Use **Changesets** so every contributor's PR articulates the impact; CI consumes changesets to bump versions + write changelog. Pre-release channels (`next`, `canary`) for risky changes. Two-week stabilization. Maintain prior major branches with security patches. Codemods for breaking migrations.

4 min read·~12 min to think through

Versioning

ChangeBump
Bug fix, no API surface changePatch
New API; existing API intactMinor
Removed/renamed/narrowed API or behaviorMajor
Type narrowing in return / type widening in required argsMajor

Changesets workflow

bash
npx changeset            # contributor adds a changeset file
# .changeset/foo-bar.md:
# ---
# "@org/lib": minor
# ---
# Added Button asChild prop.

CI runs changeset version to:

  • Bump package.json.
  • Append to CHANGELOG.md.
  • Bump dependent packages in monorepos.

Then changeset publish ships to npm.

Pre-release channels

bash
npm publish --tag next

Consumers opt in with npm i @org/lib@next. Pin canary changes for early adopters; stabilize for ~2 weeks before promoting to latest.

Release branches

For widely-used libraries, maintain prior majors:

ts
main          ← v3.x active
v2.x branch   ← v2.x security patches
v1.x branch   ← end-of-life

Publish with npm publish --tag v2 for non-current majors.

Breaking change discipline

For major bumps:

  1. Deprecate first@deprecated JSDoc + console.warn for one minor cycle.
  2. Document in MIGRATING.md with before/after examples.
  3. Codemod for non-trivial migrations (jscodeshift / ts-morph).
  4. Coexist — provide a compat layer when realistic.

Automated checks

  • Bundle size budget (size-limit) — regression fails CI.
  • Type tests (tsd, expect-type) — type changes can't slip in.
  • Visual regression (if a UI library — Chromatic / Playwright).
  • A11y (axe in stories).
  • Snapshot of API surface (api-extractor) — public API changes require explicit review.

Release rhythm

  • Patch: as often as bugs ship. Same day for security.
  • Minor: every 2–4 weeks for an active library.
  • Major: rare; usually 6–18 months apart. Big migration cost on consumers.

Pre-1.0

Semver-wise, < 1.0 means anything goes. Some libraries abuse this (every change a "minor"); strict shops still respect contract within 0.x.

Anti-patterns

  • "It's just a small breaking change" landed in a minor.
  • No changelog → consumers don't know what changed.
  • Releasing on Friday afternoon.
  • No pre-release channel → big risk every major.
  • Manual version bumps → human error in monorepos.

Interview framing

"Strict semver via Changesets — every contributor's PR drops a changeset file articulating the impact, CI consumes changesets to bump versions and write the changelog. Pre-release channel (@next) for risky changes, two-week stabilization before promotion. Maintain prior major branches with security patches. For major bumps: deprecate APIs for one minor before removing them, ship codemods for non-trivial migrations, write a MIGRATING.md. CI gates: bundle size, type tests, public API surface diff, visual regression for UI libraries. Avoid Friday releases."

Follow-up questions

  • Why Changesets over a single 'maintainer bumps version' workflow?
  • How do you handle a regression that ships to latest?
  • What's an API surface snapshot?

Common mistakes

  • Breaking change in a minor.
  • No changelog.
  • No deprecation cycle.
  • Friday releases.

Performance considerations

  • CI cost of release pipeline. Bundle/test gates pay back in regressions caught.

Edge cases

  • Monorepo: dependent packages bump correctly.
  • 0.x semver looseness.
  • Hotfix for a security bug across all maintained majors.

Real-world examples

  • Next.js release cadence, React's deprecation+migration cycles, MUI's Changesets-based workflow.

Senior engineer discussion

Seniors design the release pipeline (changesets, pre-release, gates) up front, and treat the changelog as a contract with consumers.

Related questions