Laravel 9 and the New Yearly Release Cadence
· Jerwin Arnado
Archive note: this is a backdated post, written years later while rebuilding this site. It’s dated to the moment it covers, but the hindsight is real.
Laravel 9 landed on February 8, about five months later than the old schedule would have put it. The delay is the headline feature: Laravel is moving from two major releases a year to one major release per year, with version 9 deliberately pushed back to sit on top of Symfony 6’s components.
Why the cadence change is the real story
The old six-month major cycle meant “Laravel 7” projects became “legacy” before some of them launched. For agencies and client work — my world — version churn is a real line item: every major bump is upgrade testing, dependency negotiation, and a client conversation about paying for invisible work.
One major per year (with security fixes extending accordingly) means upgrade planning becomes an annual ritual instead of a recurring scramble. It also signals something about the framework’s age, in a good way: Laravel is no longer sprinting to add table-stakes features. It’s a mature platform optimizing for the people running real systems on it. Boring on purpose is what infrastructure is supposed to be.
After 8’s Jetstream drama, a calm, structural release is also just… nice.
What’s actually in the box
- PHP 8.0 minimum. The floor rises, and the framework’s own internals now use the 8.x goodies — which means idiomatic modern PHP in the docs and generated code, not just permission to use it yourself.
- Symfony Mailer replaces SwiftMailer. SwiftMailer is end-of-life; this is the biggest forced migration in the release. If you send mail (everyone sends mail), read this section of the upgrade guide twice.
- Enum attribute casting & implicit route binding. Eloquent
$caststo native enums, and route parameters that hydrate into enum instances —Route::get('/orders/{status}', ...)rejecting invalid statuses at the routing layer. The 8.1 enum story is now end-to-end. - Controller route groups.
Route::controller(OrderController::class)->group(...)— small, tidies real files. - Anonymous migration classes by default. Kills the class-name-collision problem on long-lived projects. If you’ve ever renamed
CreateUsersTable2, you know. - Flysystem 3 under the Storage facade — another check-the-upgrade-guide item if you do anything custom with disks.
- Rendered mailable preview in the browser and assorted quality-of-life:
str()/to_route()helpers, forced scope bindings, a new query builder interface that finally gives IDEs and static analysis a fighting chance withwhere()chains.
Upgrade posture
For client projects: no rush — Laravel 8 gets security fixes for a while yet, and the Mailer/Flysystem changes mean this isn’t a coffee-break upgrade for apps with custom mail or storage code. For anything greenfield: start on 9 without hesitation, PHP 8.1, enums everywhere.
The meta-note I keep coming back to: between PHP’s annual November release and Laravel’s new annual cycle, the stack now has a rhythm. Language in November, framework in Q1, ecosystem catches up by mid-year. You can plan a year of maintenance around that. For those of us who measure projects in years rather than sprints, predictability is the most underrated feature any platform ships.