Laravel 13 today: what six months of releases delivered
Laravel 13 came out in March as what the release notes call a relatively minor upgrade in effort, and the framework has kept shipping through the minors since. I have spent those six months building a SaaS on it. The headline features get the attention, but the parts that changed my weekdays are smaller, and most of them delete boilerplate.
What does a stability-first release mean in practice?#
The release notes put it plainly: "Much of our focus during this release cycle has been minimizing breaking changes." The page follows up with the sentence I would put on the upgrade PR: "most Laravel applications may upgrade to Laravel 13 without changing much application code." The floor moves to PHP 8.3, which for a codebase already on modern PHP costs nothing. Upgrading is supposed to be cheap. What the six months actually bought me fills the rest of this article.
Attributes put the config next to the class#
The loudest developer-facing change is native PHP attributes across the framework: controllers, jobs, console commands, models, fifteen-plus locations, all optional and backward compatible (Laravel News). Middleware and authorization checks can now sit directly on the class and its methods:
#[Middleware('auth')]
class CommentController
{
#[Middleware('subscribed')]
#[Authorize('create', [Comment::class, 'post'])]
public function store(Post $post)
{
// ...
}
}Job-side controls came along too: #[Tries], #[Backoff], #[Timeout], #[FailOnTimeout]. My verdict after half a year: I use attributes where the old style scattered one fact across three files, and my fingers still type $tries = 3 where they always did. Both styles compile, which is exactly what a stability release should ship.
The small ones delete real code#
Three additions I would not want to give back:
- Queue routing by class:
Queue::route(Job::class, connection: 'redis', queue: 'podcasts')puts every routing decision in one central place. On a multitenancy app, where a job landing on the wrong connection is a security topic, one table of routes beats hunting dispatch sites. My queued Telegram alerts are exactly that kind of job. - Cache::touch(): PR #55954 extends a cache TTL without fetching and re-storing the value, so Redis answers a single
EXPIREinstead of a round trip for the whole payload. Sliding session windows stop being a get-then-put dance. - PreventRequestForgery: the CSRF middleware formalized with origin-aware verification, token-based checks still supported. The kind of default you want already on when the attack class shows up in the news.
What the minors added since March#
The release was a start, not a stop. Laravel treats minor versions as a delivery channel, and the changelog shows it: the newest framework entries date to August. That month brought a #[DebounceFor] attribute that collapses a burst of events on the same resource into one queued run, automatic retry of safe Redis commands after a transient connection failure (tunable through REDIS_COMMAND_RETRIES), queue:pause --all for the day everything is on fire, and a read-through filesystem driver that migrates files to a new disk as they are requested. The attribute wave from March is still rolling, and the queue and cache surfaces I lean on daily keep getting quieter.
The vector story widened in the same month. An AsVector Eloquent cast treats vector columns as plain arrays of floats, and the same whereVectorSimilarTo methods now compile against MariaDB's vector functions too. Semantic search is becoming ordinary Laravel, which is exactly what I want from it.
The AI SDK and the quiet vector search underneath#
The announcement leads with the first-party AI SDK: one API for text generation, tool-calling agents, embeddings, audio, images, and vector-store integrations, provider-agnostic by design. I have not shipped a feature on it yet, so I will not pretend to a review. The SDK keeps iterating underneath me, and August taught agents to recover from unknown tool calls. Underneath it sits the part I would actually build on first: native vector queries in the query builder. whereVectorSimilarTo('embedding', '…') against PostgreSQL plus pgvector, with embeddings generated straight from strings, makes semantic search a query instead of a side project.
Should you upgrade before the calendar decides?#
The support table gives the real deadline. Laravel 12 stopped receiving bug fixes on August 13, 2026, six weeks back as I write this, and its security fixes end February 24, 2027 (Laravel News). Laravel 13 gets bug fixes through Q3 2027 and security fixes until March 2028. An upgrade the release notes themselves describe as low-effort is cheap now and due by February.
For the problems in my multitenancy article, this release changes nothing. That is what a stability release is for.