Writing
·1 min read·matt

CalVer is just better

For years I used semantic versioning in both my personal and professional projects. Recently I've been using calendar versioning instead and CalVer is just better.

SemVer's pitch is that the version number means something real. Major.Minor.Patch: Major is for breaking changes, Minor for additions, Patch for fixes. The problem is "breaking" means something different to every team. I've shipped things I'd call a patch that another team called a major. The spec doesn't define this clearly enough to matter, so the number ends up signaling intent and that's about it.

I've also seen libraries bump to 2.0 with nothing practically changed and patch releases that wrecked my build anyway. It stops meaning anything.

CalVer doesn't try to encode all of that. It just tells you when something shipped. Ubuntu is the most obvious example. 24.04, 25.10 — I know immediately when it came out and whether it's an LTS release, no changelog required. Black and pip went the same direction. For Cascade Chat I use a monthly scheme with an increment for multiple releases in the same month and -rc.<run> for release candidates. When I break something I post a notice, which I'd have to do under SemVer anyway.

Library code is where I think CalVer actually wins. If I pull something at 2024.01 and it's mid-2026 I immediately know that library has been sitting cold for eighteen months. Do I keep using it, look for active forks, think about security patches? A library at 4.2.1 tells me none of that.

The hard parts of upgrading are still there. I just stopped expecting the version number to tell me about them.