Semver: A Contract Between You and Your Users
Semantic Versioning (semver) is a versioning scheme that communicates the nature of changes. When you see 2.1.0 → 2.2.0, you know it's a backward-compatible addition. When you see 2.1.0 → 3.0.0, you know something broke.
The Format: MAJOR.MINOR.PATCH
| Component | When to Bump | Example |
|---|---|---|
| MAJOR | Breaking changes — API incompatible with previous version | 1.0.0 → 2.0.0 |
| MINOR | New features — backward compatible additions | 1.0.0 → 1.1.0 |
| PATCH | Bug fixes — backward compatible fixes | 1.0.0 → 1.0.1 |
What Counts as a Breaking Change?
- Removing a public function or method
- Changing function parameters (removing, reordering, changing types)
- Changing return types
- Changing default behavior
- Dropping support for a runtime (Node 18 → Node 20 minimum)
- Renaming exported modules
What is NOT breaking: adding new optional parameters, adding new functions, adding new fields to response objects, performance improvements, internal refactoring.
Version Ranges in package.json
{
"dependencies": {
"exact": "1.2.3", // Only 1.2.3
"caret": "^1.2.3", // >=1.2.3 <2.0.0 (most common)
"tilde": "~1.2.3", // >=1.2.3 <1.3.0
"gte": ">=1.2.3", // 1.2.3 or higher (risky)
"range": ">=1.0.0 <3.0.0",
"wildcard": "1.x" , // >=1.0.0 <2.0.0
"latest": "*" // Any version (don't do this)
}
}| Range | Installs | Risk Level |
|---|---|---|
^1.2.3 | 1.2.3 to 1.x.x | Low — no breaking changes within major |
~1.2.3 | 1.2.3 to 1.2.x | Very low — only patches |
1.2.3 | Exactly 1.2.3 | None — but no security updates |
Pre-release Versions
1.0.0-alpha.1 // Early development, unstable
1.0.0-beta.1 // Feature-complete, may have bugs
1.0.0-rc.1 // Release candidate, ready for testing
1.0.0 // Stable releasePre-release versions have lower precedence: 1.0.0-alpha < 1.0.0-beta < 1.0.0-rc.1 < 1.0.0
Practical Rules
- Start at 0.1.0 for new projects. Before 1.0.0, anything can change.
- Release 1.0.0 when your API is used in production by others.
- Use
^(caret) in package.json — it's the default and right for most cases. - Use lockfiles (package-lock.json, yarn.lock) to pin exact versions in production.
- Automate with conventional commits + tools like
semantic-releaseorchangesets.
Parse versions: JSON Formatter — validate and format your package.json.