CalVer vs SemVer: how to pick a versioning scheme

There are two honest ways to number releases. SemVer encodes a compatibility promise: the number tells users whether upgrading will break them. CalVer encodes a date: the number tells users how old what they're running is. Most versioning arguments are really arguments about which of those two facts your users need more. This guide helps you pick — and shows what the choice does to your changelog.

What each scheme actually says

A SemVer version like 3.2.1 is a contract about compatibility: MAJOR means "breaking, read before upgrading", MINOR means "additive, upgrade blind", PATCH means "fixes only". (Full plain-English tour in our semver guide.) The number says nothing about when the release happened.

A CalVer version like 2026.07 or 24.04 is a statement of time: this is the July 2026 release. The number says nothing about whether it breaks you. Common patterns:

  • YYYY.MM — Ubuntu's 24.04, JetBrains' 2026.2.
  • YY.MM.MICRO — pip's 24.1.2: date plus a patch counter.
  • YYYY.MINOR — a year stamp with a release counter inside it.

The one question that decides it

Do people build on top of your interfaces?

If yes — a library, a framework, a CLI other scripts call, an API with client SDKs — your users' single most important question at upgrade time is "will this break me?". Only SemVer answers it in the version number itself. Pick SemVer.

If no — an application humans use, an OS, a desktop tool, a SaaS — "breaking change" is barely meaningful, because nobody programs against you. The useful facts are how old is my install and which release is this bug report about. CalVer answers both at a glance, and removes a whole category of team argument: nobody ever debates whether a release is "really a 2.0". Time passes; the number increments itself.

Where each one hurts

  • SemVer's cost is judgment. Every release forces a call on what counts as breaking — and the sneaky cases (tightened validation, changed defaults, new enum values) are genuinely hard; see our API changelog guide. Teams that dodge the judgment ship eternal 0.x, which promises nothing.
  • SemVer under marketing pressure lies. When "3.0" is a launch event, the compatibility signal corrupts: big-but-compatible releases get breaking-flagged numbers, and real breakage gets smuggled into minors to avoid scaring people.
  • CalVer can't warn. 2026.07 looks exactly as safe as 2026.06 even if it removes half the config format. Users must read the changelog — so a CalVer project with a stale changelog is flying blind.
  • CalVer implies freshness debt. If your latest release is 2024.11 and it's 2026, the version number itself advertises abandonment. Slow-and-stable projects wear SemVer better.

Hybrids and pragmatic middle grounds

  • CalVer shell, SemVer discipline. pip and setuptools use dated versions but still document breakage loudly and deprecate first. The number is a date; the process is semver-ish. This works — the warning just moves from the version string into the changelog and deprecation notices.
  • SemVer the API, CalVer the product. A SaaS can version its dashboard by date (or not at all) while its public API keeps strict SemVer or dated API versions (2026-07-01 à la Stripe). Different audiences, different promises.
  • Ubuntu's trick: make the date itself the compatibility boundary — big changes land in the next time-boxed release, and users know .04-to-.10 upgrades are the risky moments. Cadence becomes the contract (more on cadence).

What your changelog looks like under each

Under SemVer, the changelog is organized by version: every entry hangs off 3.2.0, breaking changes cluster under majors, and the Keep a Changelog format fits perfectly.

Under CalVer — and for versionless SaaS — the changelog is the timeline. Entries hang off dates, ship as they land, and tags (new / improved / fix / announcement) do the signaling that version-number positions used to do. Breaking changes can't rely on a scary MAJOR anymore, so the entry itself must be loud: "Breaking:" in the title, migration path in the body (the full playbook).

Quick reference

  • Library, SDK, framework, programmatic API → SemVer.
  • Application, OS, desktop tool, anything on a time-boxed cadence → CalVer.
  • SaaS product → dated changelog entries (CalVer in spirit); SemVer or dated versions for the public API only.
  • Whatever you pick: write it down (what the number promises, what counts as breaking) and never change schemes without an announcement.

Either way, the changelog does the talking

SemVer tells users when to read your changelog; CalVer makes the changelog the only place the story lives. Wakelog is a free hosted home for it: date-organized entries with tags, posted from a release script in one curl or via CLI, imported from your existing CHANGELOG.md or GitHub Releases in one paste, published on a public page with RSS — and exportable back to plain CHANGELOG.md anytime.

Start a free changelog   Preview your CHANGELOG.md — no signup

Related guides

Last updated 2026-07-26 · All guides