DEV Community

david duymelinck
david duymelinck

Posted on

Laravel makes semantic versioning look bad

Here I go again! I couldn't find it but I remember I did a rant about Laravel needing to pick date formatted versioning instead of semantic versioning when Laravel 12 was announced.

The reason I'm writing this is because Livewire can announce a release compatible with an unreleased major version.

Lets dive in.

Semantic versioning

The main goal of semantic versioning is to make the dependency management predictable.

It uses three sets of numbers divided by a dot. The context of the numbers from left to right is major, minor and patch.

A major number change must happen when there are backward incompatible changes. But it can also happen when multiple features and or changes are introduced.

The Laravel situation

From the commits on Github and a blog on Lavavel News The biggest change is the optional use of attributes.
While they added quite a few attributes, does this really warrant a major update?

You could argue raising the minimum required PHP version, 8.2 to 8.3, is cause for a major change.
When I look for an 8.3 feature like json_validate I see that they are are using the Symfony polyfill in version 12. So there is no need to raise the major version.

Why do they keep on using arbitrary semantic versioning?

Because it is the convention in the community?

There are no side effects if they are using the number parts as year, month and day. They could even add the time to the patch part in case they need to create multiple releases on a single day.
This means releases with backwards incompatible changes can only happen once a year.
I like the explicitness of the date versioning over the arbitrary number, you can actually see how old the version in the application is. This could open some eyes.

Are we doing semantic versioning wrong the whole time?
In the beginning of a project it is likely that backwards incompatible versions can be happen closer to each other. So in that stage the arbitrary numbering is preferred.
When the project is matured I think the step to date/calendar versioning should be taken.

PS: the post moved from rant to realization. But I kept the title for the views.

Top comments (3)

Collapse
 
charlie_waddell01 profile image
Charlie Waddell

I think this post conflates major with large, which isn’t what semantic versioning actually guarantees.

Under semantic versioning, a major version signals breaking changes - not the size, excitement level, or marketing impact of those changes. Raising the minimum required PHP version alone qualifies as a breaking change. Whether certain features are polyfilled is beside the point - the runtime requirement has changed, and that is explicitly major under the specification.

With Laravel, major releases are predictable and annual. That predictability is the opposite of arbitrary. It consolidates breaking changes into a known window and gives the ecosystem a clear upgrade cadence.

There’s also a broader platform consideration. PHP 8.2 reaches end of life in December 2026. Laravel 14 is projected to be released in March 2027. Aligning framework support with upstream lifecycle policy isn’t version inflation - it’s responsible maintenance strategy.

As for Livewire announcing compatibility ahead of a major release, that reflects ecosystem coordination, not a breakdown of semantic versioning. Mature ecosystems preparing for upcoming majors before they ship is generally a sign of stability.

That said, timing does matter. For example, Spatie recently had to adjust their CI workflow because Livewire introduced Laravel 13 support before Laravel 13 was actually released, which appears to have caused test suite instability - highlighting friction points elsewhere (see here). That's a different discussion entirely.

Calendar versioning is a valid strategy in some contexts, but it does not replace semantic guarantees. Dependency managers rely on version numbers communicating compatibility boundaries. Replacing that with pure date-based identifiers would reduce clarity, not increase it.

If anything, Laravel’s approach is a hybrid: time-based major cadence with semantic compatibility rules inside that cadence. That’s not misuse of semantic versioning - it’s disciplined use of it.

Collapse
 
xwero profile image
david duymelinck

I couldn't find anything about runtime changes in the specification, only backward incompatible changes. If the code doesn't use any of the breaking changes from the language version semantic versioning doesn't care.

The polyfill does matter because json_validate is introduced in 8.3, therefor using it in Laravel 13 would make it a breaking change without the polyfill.

How does calendar versioning makes communicating compatibility boundaries more difficult?
The numbers only go up.
Semantic versioning doesn't care if it is 9 or 20 or 2026. You can skip numbers as long as they go up.

First you mention a major change only has to do with breaking changes, but in the end you mention it is also time based. So why can it not be also marketing driven, introducing a slew of new features or any other reason the developer thinks it warrants a major change?

The change I suggest is for every project that uses a yearly cycle. If they don't then it wouldn't make sense.

Collapse
 
charlie_waddell01 profile image
Charlie Waddell

I think we’re circling a few different layers of the discussion.

On the runtime point: semantic versioning defines a major release as one that introduces incompatible changes. If a package raises its minimum PHP requirement, consumers running the previous version can no longer install or run it. That’s an incompatibility, even if the framework doesn’t use new language features directly. The breaking surface isn’t "does this code call a new function", it’s "can existing consumers continue using this version without changing their environment". In that sense, a runtime bump is unambiguously major under sem ver.

You’re right that polyfills matter when maintaining compatibility with older runtimes. But once the declared minimum version changes, the polyfill becomes irrelevant to versioning semantics - the incompatibility is the constraint itself.

On calendar versioning: you’re correct that sem ver doesn’t care whether the number is 9, 20, or 2026 - only that it increases. The difference isn’t about the size of the number, it’s about encoded meaning. With sem ver, MAJOR/MINOR/PATCH communicate compatibility expectations structurally. With pure calendar versioning such as 2027.03, that compatibility meaning has to be reintroduced via policy documentation. At that point, you’re effectively recreating sem ver rules on top of date-based identifiers.

Regarding cadence: there’s no contradiction between "major means breaking" and "majors are released yearly". The yearly schedule defines when breaking changes are consolidated. Sem ver defines how those breaking changes are signaled. One is release governance, the other is compatibility communication.

Could a project bump a major for marketing reasons? Absolutely - sem ver doesn’t prohibit that. But doing so weakens the informational value of the signal over time. The strength of something like Laravel is that its annual majors reliably correspond to real compatibility boundaries (mostly anyway), even if those changes are incremental rather than dramatic.

I actually think your suggestion makes sense for projects that are purely time-driven. But Laravel already operates as a hybrid: predictable annual majors combined with semantic compatibility guarantees. Switching to pure calendar identifiers wouldn’t meaningfully increase clarity - it would mostly change the aesthetics of the number.

I suspect we may just be optimising for different things: you’re valuing visible release age, while I’m valuing encoded compatibility boundaries. Both are reasonable priorities - they just solve different problems.